@hyperdrive.bot/bmad-workflow 1.0.3 → 1.0.6
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/README.md +373 -790
- package/dist/models/provider.d.ts +1 -1
- package/dist/models/provider.js +5 -0
- package/dist/services/agents/agent-runner-factory.js +5 -1
- package/dist/services/agents/index.d.ts +1 -0
- package/dist/services/agents/index.js +1 -0
- package/dist/services/agents/opencode-agent-runner.d.ts +92 -0
- package/dist/services/agents/opencode-agent-runner.js +392 -0
- package/dist/services/orchestration/task-decomposition-service.js +79 -126
- package/package.json +1 -1
|
@@ -159,70 +159,38 @@ ${options.contextFiles.map((f) => `- ${f}`).join('\n')}
|
|
|
159
159
|
`;
|
|
160
160
|
}
|
|
161
161
|
// Add output format instructions (varies based on story format mode)
|
|
162
|
-
prompt += options.storyFormat ? `## OUTPUT FORMAT - STORY MODE
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
\`\`\`yaml
|
|
162
|
+
prompt += options.storyFormat ? `## OUTPUT FORMAT - STORY MODE - CRITICAL INSTRUCTIONS
|
|
163
|
+
|
|
164
|
+
**YOUR RESPONSE MUST BE PURE YAML ONLY.**
|
|
165
|
+
- Do NOT write any explanation, summary, or commentary
|
|
166
|
+
- Do NOT use markdown code fences
|
|
167
|
+
- Start your response DIRECTLY with "masterPrompt: |"
|
|
168
|
+
|
|
169
|
+
Each task becomes a BMAD story with user story format, acceptance criteria, and tasks breakdown.
|
|
170
|
+
|
|
171
|
+
The YAML structure MUST be:
|
|
172
|
+
|
|
174
173
|
masterPrompt: |
|
|
175
|
-
A reusable prompt template
|
|
176
|
-
Include best practices
|
|
174
|
+
A reusable prompt template for all stories.
|
|
175
|
+
Include best practices and coding standards.
|
|
177
176
|
|
|
178
177
|
tasks:
|
|
179
178
|
- id: ${options.storyPrefix}-001
|
|
180
179
|
title: "Clear, specific story title"
|
|
181
180
|
description: "High-level description of what this story delivers"
|
|
182
181
|
estimatedMinutes: 10
|
|
183
|
-
dependencies: []
|
|
182
|
+
dependencies: []
|
|
184
183
|
parallelizable: true
|
|
185
184
|
agentType: "dev"
|
|
186
|
-
targetFiles:
|
|
185
|
+
targetFiles:
|
|
187
186
|
- "path/to/file.js"
|
|
188
187
|
prompt: |
|
|
189
|
-
Create a story following BMAD story format:
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
## Story
|
|
197
|
-
**As a** [role/persona],
|
|
198
|
-
**I want** [capability/feature],
|
|
199
|
-
**so that** [benefit/value]
|
|
200
|
-
|
|
201
|
-
## Acceptance Criteria
|
|
202
|
-
1. [Specific, testable criterion]
|
|
203
|
-
2. [Another criterion]
|
|
204
|
-
3. [Another criterion]
|
|
205
|
-
|
|
206
|
-
## Tasks / Subtasks
|
|
207
|
-
- [ ] Task 1: [Description] (AC: #1)
|
|
208
|
-
- [ ] Subtask 1.1: [Specific action]
|
|
209
|
-
- [ ] Subtask 1.2: [Specific action]
|
|
210
|
-
- [ ] Task 2: [Description] (AC: #2)
|
|
211
|
-
- [ ] Subtask 2.1: [Specific action]
|
|
212
|
-
|
|
213
|
-
## Dev Notes
|
|
214
|
-
[Relevant architecture info, integration points, file locations]
|
|
215
|
-
|
|
216
|
-
### Testing
|
|
217
|
-
- Test file location: [path]
|
|
218
|
-
- Test standards: [requirements]
|
|
219
|
-
- Testing frameworks: [tools being used]
|
|
220
|
-
- Specific requirements: [any special test needs]
|
|
221
|
-
|
|
222
|
-
## Change Log
|
|
223
|
-
| Date | Version | Description | Author |
|
|
224
|
-
|------|---------|-------------|--------|
|
|
225
|
-
| [Date] | 1.0 | Story created | AI Agent |
|
|
188
|
+
Create a story following BMAD story format with:
|
|
189
|
+
- Status: Draft
|
|
190
|
+
- User story (As a... I want... so that...)
|
|
191
|
+
- Acceptance Criteria (numbered, testable)
|
|
192
|
+
- Tasks/Subtasks with AC references
|
|
193
|
+
- Dev Notes with testing info
|
|
226
194
|
outputFile: "${sessionDir}/stories/${options.storyPrefix}-001.md"
|
|
227
195
|
|
|
228
196
|
- id: ${options.storyPrefix}-002
|
|
@@ -233,40 +201,25 @@ tasks:
|
|
|
233
201
|
parallelizable: false
|
|
234
202
|
agentType: "dev"
|
|
235
203
|
prompt: |
|
|
236
|
-
|
|
204
|
+
Story-formatted prompt
|
|
237
205
|
outputFile: "${sessionDir}/stories/${options.storyPrefix}-002.md"
|
|
238
206
|
|
|
239
|
-
|
|
240
|
-
|
|
207
|
+
## STORY MODE RULES
|
|
208
|
+
- Task IDs: ${options.storyPrefix}-001, ${options.storyPrefix}-002, etc.
|
|
209
|
+
- Output files: ${sessionDir}/stories/
|
|
210
|
+
${options.perFile ? '- **CRITICAL**: Create one story per file (per-file mode is ON)' : ''}
|
|
241
211
|
|
|
242
|
-
**
|
|
243
|
-
|
|
244
|
-
- Output files MUST go to stories/ directory
|
|
245
|
-
- Prompts MUST generate full story structure (not simple task outputs)
|
|
246
|
-
- Each story must have user story format, acceptance criteria, and tasks breakdown
|
|
212
|
+
**REMEMBER: Your ENTIRE response must be valid YAML starting with "masterPrompt: |" - NO other text!**
|
|
213
|
+
` : `## OUTPUT FORMAT - CRITICAL INSTRUCTIONS
|
|
247
214
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
5. Stories with the same dependencies can run in parallel (if parallelizable: true)
|
|
254
|
-
6. All file paths in outputFile should use the session directory: ${sessionDir}/stories/
|
|
255
|
-
${options.perFile ? '7. **CRITICAL**: Create one story per file for the main work (per-file mode is ON)' : ''}
|
|
215
|
+
**YOUR RESPONSE MUST BE PURE YAML ONLY.**
|
|
216
|
+
- Do NOT write any explanation, summary, or commentary
|
|
217
|
+
- Do NOT use markdown code fences (\`\`\`yaml or \`\`\`)
|
|
218
|
+
- Do NOT write "Here's the task decomposition..." or similar
|
|
219
|
+
- Start your response DIRECTLY with "masterPrompt: |"
|
|
256
220
|
|
|
257
|
-
|
|
221
|
+
The YAML structure MUST be:
|
|
258
222
|
|
|
259
|
-
Sequential:
|
|
260
|
-
${options.storyPrefix}-001 (deps: []) → ${options.storyPrefix}-002 (deps: [${options.storyPrefix}-001])
|
|
261
|
-
|
|
262
|
-
Parallel then join:
|
|
263
|
-
${options.storyPrefix}-001 (deps: []) → [${options.storyPrefix}-002, ${options.storyPrefix}-003] → ${options.storyPrefix}-004
|
|
264
|
-
|
|
265
|
-
Now, decompose the goal into stories. Output ONLY the YAML structure.
|
|
266
|
-
` : `## OUTPUT FORMAT
|
|
267
|
-
You MUST output ONLY valid YAML in the following structure. DO NOT include markdown code fences or any other text.
|
|
268
|
-
|
|
269
|
-
\`\`\`yaml
|
|
270
223
|
masterPrompt: |
|
|
271
224
|
A reusable prompt template that applies to all tasks.
|
|
272
225
|
Include best practices, coding standards, and common guidelines.
|
|
@@ -276,52 +229,39 @@ tasks:
|
|
|
276
229
|
title: "Clear, specific task title"
|
|
277
230
|
description: "Detailed description of what this task accomplishes"
|
|
278
231
|
estimatedMinutes: 10
|
|
279
|
-
dependencies: []
|
|
280
|
-
parallelizable: true
|
|
281
|
-
agentType: "dev"
|
|
282
|
-
targetFiles:
|
|
232
|
+
dependencies: []
|
|
233
|
+
parallelizable: true
|
|
234
|
+
agentType: "dev"
|
|
235
|
+
targetFiles:
|
|
283
236
|
- "path/to/file.js"
|
|
284
237
|
prompt: |
|
|
285
238
|
Specific prompt for the agent to execute this task.
|
|
286
|
-
Include
|
|
287
|
-
- What to do
|
|
288
|
-
- Where to do it (file paths)
|
|
289
|
-
- Expected outcome
|
|
290
|
-
- Any validation steps
|
|
239
|
+
Include what to do, where to do it, expected outcome, validation steps.
|
|
291
240
|
outputFile: "${sessionDir}/outputs/task-001-output.md"
|
|
292
241
|
|
|
293
242
|
- id: task-002
|
|
294
243
|
title: "Next task"
|
|
295
244
|
description: "Task description"
|
|
296
245
|
estimatedMinutes: 5
|
|
297
|
-
dependencies: ["task-001"]
|
|
246
|
+
dependencies: ["task-001"]
|
|
298
247
|
parallelizable: false
|
|
299
248
|
agentType: "dev"
|
|
300
249
|
prompt: |
|
|
301
250
|
Task-specific prompt here
|
|
302
251
|
outputFile: "${sessionDir}/outputs/task-002-output.md"
|
|
303
252
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
## IMPORTANT RULES
|
|
308
|
-
1. Each task ID must be unique
|
|
253
|
+
## YAML RULES
|
|
254
|
+
1. Each task ID must be unique (task-001, task-002, etc.)
|
|
309
255
|
2. Dependencies must reference valid task IDs
|
|
310
|
-
3.
|
|
311
|
-
4.
|
|
312
|
-
5.
|
|
313
|
-
6. All file paths in outputFile should use the session directory: ${sessionDir}/outputs/
|
|
314
|
-
${options.perFile ? '7. **CRITICAL**: Create one task per file for the main work (per-file mode is ON)' : ''}
|
|
315
|
-
|
|
316
|
-
## EXAMPLE DEPENDENCY PATTERNS
|
|
317
|
-
|
|
318
|
-
Sequential:
|
|
319
|
-
task-001 (deps: []) → task-002 (deps: [task-001]) → task-003 (deps: [task-002])
|
|
256
|
+
3. No circular dependencies
|
|
257
|
+
4. Use outputFile path: ${sessionDir}/outputs/
|
|
258
|
+
${options.perFile ? '5. **CRITICAL**: Create one task per file (per-file mode is ON)' : ''}
|
|
320
259
|
|
|
321
|
-
|
|
322
|
-
|
|
260
|
+
## DEPENDENCY PATTERNS
|
|
261
|
+
- Sequential: task-001 → task-002 (deps: [task-001])
|
|
262
|
+
- Parallel: task-002, task-003 both depend on task-001, then task-004 depends on both
|
|
323
263
|
|
|
324
|
-
|
|
264
|
+
**REMEMBER: Your ENTIRE response must be valid YAML starting with "masterPrompt: |" - NO other text!**
|
|
325
265
|
`;
|
|
326
266
|
return prompt;
|
|
327
267
|
}
|
|
@@ -418,15 +358,25 @@ Now, decompose the goal into tasks. Output ONLY the YAML structure.
|
|
|
418
358
|
startIndex = lines.findIndex((line) => line.trim().startsWith('tasks:'));
|
|
419
359
|
}
|
|
420
360
|
if (startIndex !== -1) {
|
|
421
|
-
//
|
|
361
|
+
// For YAML task graphs, we expect the content to continue until the end
|
|
362
|
+
// since ## headers inside multiline strings (prompt: |) are valid YAML content.
|
|
363
|
+
// Only stop if we see clear non-YAML markers at the start of a line (no indentation).
|
|
422
364
|
let endIndex = lines.length;
|
|
423
365
|
for (let i = startIndex + 1; i < lines.length; i++) {
|
|
424
|
-
const line = lines[i]
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
366
|
+
const line = lines[i];
|
|
367
|
+
const trimmedLine = line.trim();
|
|
368
|
+
// Only stop at lines that are:
|
|
369
|
+
// 1. Not indented (start at column 0)
|
|
370
|
+
// 2. Look like markdown headers or prose (not YAML keys)
|
|
371
|
+
// 3. Are not empty lines (which are valid in YAML)
|
|
372
|
+
if (line.length > 0 && line[0] !== ' ' && line[0] !== '\t') {
|
|
373
|
+
// Line is not indented - check if it's a YAML key or non-YAML content
|
|
374
|
+
const isYamlKey = /^[a-zA-Z_][a-zA-Z0-9_]*:/.test(trimmedLine) || trimmedLine.startsWith('-');
|
|
375
|
+
if (!isYamlKey && !trimmedLine.startsWith('#')) {
|
|
376
|
+
// Non-indented, non-YAML content (like "Here's the summary...")
|
|
377
|
+
endIndex = i;
|
|
378
|
+
break;
|
|
379
|
+
}
|
|
430
380
|
}
|
|
431
381
|
}
|
|
432
382
|
const yamlContent = lines.slice(startIndex, endIndex).join('\n');
|
|
@@ -535,21 +485,24 @@ Now, decompose the goal into tasks. Output ONLY the YAML structure.
|
|
|
535
485
|
catch (error) {
|
|
536
486
|
this.logger.warn({ error: error.message }, 'YAML validation failed, asking Claude to fix it');
|
|
537
487
|
// YAML is invalid, ask Claude to fix it
|
|
538
|
-
const fixPrompt = `
|
|
488
|
+
const fixPrompt = `FIX THIS YAML - OUTPUT ONLY THE FIXED YAML, NOTHING ELSE.
|
|
489
|
+
|
|
490
|
+
**CRITICAL: Your response must be PURE YAML only. Start directly with "masterPrompt: |"**
|
|
491
|
+
- Do NOT write any explanation
|
|
492
|
+
- Do NOT use markdown code fences
|
|
493
|
+
- Do NOT say "Here's the fixed YAML" or anything similar
|
|
539
494
|
|
|
540
|
-
ERROR: ${error.message}
|
|
495
|
+
ERROR TO FIX: ${error.message}
|
|
541
496
|
|
|
542
|
-
|
|
497
|
+
YAML TO FIX:
|
|
543
498
|
${output}
|
|
544
499
|
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
4. No syntax errors remain
|
|
500
|
+
RULES:
|
|
501
|
+
- Use 2 spaces for indentation
|
|
502
|
+
- Quote strings with special characters
|
|
503
|
+
- Ensure valid YAML syntax
|
|
550
504
|
|
|
551
|
-
|
|
552
|
-
`;
|
|
505
|
+
YOUR RESPONSE MUST START WITH "masterPrompt: |" - NO OTHER TEXT ALLOWED!`;
|
|
553
506
|
this.logger.info('Asking Claude to fix YAML errors');
|
|
554
507
|
const fixResult = await this.agentRunner.runAgent(fixPrompt, {
|
|
555
508
|
agentType: 'architect',
|
package/package.json
CHANGED