@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,97 @@
1
+ import { Command } from '@oclif/core';
2
+ /**
3
+ * Workflow Command
4
+ *
5
+ * Orchestrates the complete PRD → Epic → Story → Dev pipeline from a single entry point.
6
+ * Provides visual progress indicators, dry-run support, and graceful cancellation.
7
+ *
8
+ * @example
9
+ * ```bash
10
+ * # Start workflow from PRD
11
+ * bmad-workflow workflow docs/PRD-feature.md
12
+ *
13
+ * # Start from epic, skip dev
14
+ * bmad-workflow workflow docs/epics/epic-1.md --skip-dev
15
+ *
16
+ * # Dry run to preview actions
17
+ * bmad-workflow workflow docs/PRD-feature.md --dry-run
18
+ * ```
19
+ */
20
+ export default class Workflow extends Command {
21
+ static args: {
22
+ input: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
23
+ };
24
+ static description: string;
25
+ static examples: string[];
26
+ static flags: {
27
+ 'auto-fix': import("@oclif/core/interfaces").BooleanFlag<boolean>;
28
+ cwd: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
29
+ 'dry-run': import("@oclif/core/interfaces").BooleanFlag<boolean>;
30
+ 'epic-interval': import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
31
+ parallel: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
32
+ pipeline: import("@oclif/core/interfaces").BooleanFlag<boolean>;
33
+ 'prd-interval': import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
34
+ prefix: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
35
+ provider: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
36
+ qa: import("@oclif/core/interfaces").BooleanFlag<boolean>;
37
+ 'qa-prompt': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
38
+ 'qa-retries': import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
39
+ reference: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
40
+ 'skip-dev': import("@oclif/core/interfaces").BooleanFlag<boolean>;
41
+ 'skip-epics': import("@oclif/core/interfaces").BooleanFlag<boolean>;
42
+ 'skip-stories': import("@oclif/core/interfaces").BooleanFlag<boolean>;
43
+ 'story-interval': import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
44
+ verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
45
+ };
46
+ private cancelled;
47
+ private logger;
48
+ private orchestrator;
49
+ /**
50
+ * Main command execution
51
+ *
52
+ * Orchestrates the complete workflow with progress tracking and summary display.
53
+ */
54
+ run(): Promise<void>;
55
+ /**
56
+ * Display dry-run banner
57
+ *
58
+ * Shows prominent message that workflow is in dry-run mode.
59
+ * @private
60
+ */
61
+ private displayDryRunBanner;
62
+ /**
63
+ * Display final summary with phase results
64
+ *
65
+ * Shows table with success/failure counts and durations for each phase.
66
+ *
67
+ * @param result - Workflow result with all phase data
68
+ * @param config - Workflow configuration used
69
+ * @private
70
+ */
71
+ private displayFinalSummary;
72
+ /**
73
+ * Display phase header with visual separator
74
+ *
75
+ * @param phaseNumber - Current phase number (1-based)
76
+ * @param totalPhases - Total number of phases
77
+ * @param phaseName - Name of the phase
78
+ * @private
79
+ */
80
+ private displayPhaseHeader;
81
+ /**
82
+ * Initialize services and dependencies
83
+ *
84
+ * Creates all service instances needed for workflow orchestration.
85
+ * @param maxConcurrency - Maximum number of concurrent operations
86
+ * @param provider - AI provider to use (claude or gemini)
87
+ * @private
88
+ */
89
+ private initializeServices;
90
+ /**
91
+ * Register SIGINT handler for graceful cancellation
92
+ *
93
+ * Allows user to cancel workflow with Ctrl+C, completing current operation first.
94
+ * @private
95
+ */
96
+ private registerSignalHandlers;
97
+ }
@@ -0,0 +1,390 @@
1
+ import { Args, Command, Flags } from '@oclif/core';
2
+ import { createAgentRunner, isProviderSupported } from '../services/agents/agent-runner-factory.js';
3
+ import { FileManager } from '../services/file-system/file-manager.js';
4
+ import { PathResolver } from '../services/file-system/path-resolver.js';
5
+ import { BatchProcessor } from '../services/orchestration/batch-processor.js';
6
+ import { InputDetector } from '../services/orchestration/input-detector.js';
7
+ import { StoryTypeDetector } from '../services/orchestration/story-type-detector.js';
8
+ import { WorkflowOrchestrator } from '../services/orchestration/workflow-orchestrator.js';
9
+ import { EpicParser } from '../services/parsers/epic-parser.js';
10
+ import { PrdParser } from '../services/parsers/prd-parser.js';
11
+ import * as colors from '../utils/colors.js';
12
+ import { formatBox, formatTable } from '../utils/formatters.js';
13
+ import { createLogger } from '../utils/logger.js';
14
+ /**
15
+ * Workflow Command
16
+ *
17
+ * Orchestrates the complete PRD → Epic → Story → Dev pipeline from a single entry point.
18
+ * Provides visual progress indicators, dry-run support, and graceful cancellation.
19
+ *
20
+ * @example
21
+ * ```bash
22
+ * # Start workflow from PRD
23
+ * bmad-workflow workflow docs/PRD-feature.md
24
+ *
25
+ * # Start from epic, skip dev
26
+ * bmad-workflow workflow docs/epics/epic-1.md --skip-dev
27
+ *
28
+ * # Dry run to preview actions
29
+ * bmad-workflow workflow docs/PRD-feature.md --dry-run
30
+ * ```
31
+ */
32
+ export default class Workflow extends Command {
33
+ static args = {
34
+ input: Args.string({
35
+ description: 'PRD file, epic file, or story pattern to start workflow from',
36
+ required: true,
37
+ }),
38
+ };
39
+ static description = 'Execute complete PRD → Epic → Story → Dev workflow with progress tracking';
40
+ static examples = [
41
+ '<%= config.bin %> <%= command.id %> docs/PRD-feature.md',
42
+ '<%= config.bin %> <%= command.id %> docs/epics/epic-1.md --skip-dev',
43
+ '<%= config.bin %> <%= command.id %> docs/PRD-feature.md --dry-run --verbose',
44
+ '<%= config.bin %> <%= command.id %> "docs/stories/STORY-*.md" --skip-epics --skip-stories',
45
+ ];
46
+ static flags = {
47
+ 'auto-fix': Flags.boolean({
48
+ default: false,
49
+ description: 'Auto-fix PRD format using AI when parsing fails',
50
+ }),
51
+ cwd: Flags.string({
52
+ description: 'Working directory path to pass to AI agents. Agents will operate in this directory.',
53
+ }),
54
+ 'dry-run': Flags.boolean({
55
+ default: false,
56
+ description: 'Preview actions without execution',
57
+ }),
58
+ 'epic-interval': Flags.integer({
59
+ default: 60,
60
+ description: 'Seconds between story creation batches',
61
+ }),
62
+ parallel: Flags.integer({
63
+ default: 3,
64
+ description: 'Max concurrent epic/story creations',
65
+ }),
66
+ pipeline: Flags.boolean({
67
+ allowNo: true,
68
+ default: true,
69
+ description: 'Enable pipelined workflow (start dev on stories sequentially as they are created)',
70
+ }),
71
+ 'prd-interval': Flags.integer({
72
+ default: 60,
73
+ description: 'Seconds between epic creation batches',
74
+ }),
75
+ prefix: Flags.string({
76
+ default: '',
77
+ description: 'Filename prefix for generated files',
78
+ }),
79
+ provider: Flags.string({
80
+ default: 'claude',
81
+ description: 'AI provider to use (claude or gemini)',
82
+ options: ['claude', 'gemini'],
83
+ }),
84
+ qa: Flags.boolean({
85
+ default: false,
86
+ description: 'Run QA workflow after development completes',
87
+ helpGroup: 'QA Workflow',
88
+ }),
89
+ 'qa-prompt': Flags.string({
90
+ description: 'Custom prompt/instructions for QA review phase',
91
+ helpGroup: 'QA Workflow',
92
+ }),
93
+ 'qa-retries': Flags.integer({
94
+ default: 2,
95
+ description: 'Maximum QA → Dev fix cycles (only used with --qa)',
96
+ helpGroup: 'QA Workflow',
97
+ }),
98
+ reference: Flags.string({
99
+ description: 'Additional context files for AI agents (can be used multiple times)',
100
+ multiple: true,
101
+ }),
102
+ 'skip-dev': Flags.boolean({
103
+ default: false,
104
+ description: 'Skip development phase',
105
+ }),
106
+ 'skip-epics': Flags.boolean({
107
+ default: false,
108
+ description: 'Skip epic creation phase',
109
+ }),
110
+ 'skip-stories': Flags.boolean({
111
+ default: false,
112
+ description: 'Skip story creation phase',
113
+ }),
114
+ 'story-interval': Flags.integer({
115
+ default: 60,
116
+ description: 'Seconds between story development',
117
+ }),
118
+ verbose: Flags.boolean({
119
+ char: 'v',
120
+ default: false,
121
+ description: 'Detailed output mode',
122
+ }),
123
+ };
124
+ cancelled = false;
125
+ logger;
126
+ orchestrator;
127
+ /**
128
+ * Main command execution
129
+ *
130
+ * Orchestrates the complete workflow with progress tracking and summary display.
131
+ */
132
+ async run() {
133
+ const { args, flags } = await this.parse(Workflow);
134
+ try {
135
+ // Validate provider
136
+ if (!isProviderSupported(flags.provider)) {
137
+ this.error(`Unsupported provider: ${flags.provider}. Use 'claude' or 'gemini'.`, { exit: 1 });
138
+ }
139
+ // Initialize services with parallel concurrency and provider
140
+ await this.initializeServices(flags.parallel, flags.provider);
141
+ // Register signal handlers
142
+ this.registerSignalHandlers();
143
+ // Show dry-run banner if applicable
144
+ if (flags['dry-run']) {
145
+ this.displayDryRunBanner();
146
+ }
147
+ // Build workflow configuration
148
+ const config = {
149
+ autoFix: flags['auto-fix'],
150
+ cwd: flags.cwd,
151
+ dryRun: flags['dry-run'],
152
+ epicInterval: flags['epic-interval'],
153
+ input: args.input,
154
+ parallel: flags.parallel,
155
+ pipeline: flags.pipeline,
156
+ prdInterval: flags['prd-interval'],
157
+ prefix: flags.prefix,
158
+ provider: flags.provider,
159
+ qa: flags.qa,
160
+ qaPrompt: flags['qa-prompt'],
161
+ qaRetries: flags['qa-retries'],
162
+ references: flags.reference || [],
163
+ skipDev: flags['skip-dev'],
164
+ skipEpics: flags['skip-epics'],
165
+ skipStories: flags['skip-stories'],
166
+ storyInterval: flags['story-interval'],
167
+ verbose: flags.verbose,
168
+ };
169
+ // Log configuration if verbose
170
+ if (flags.verbose) {
171
+ this.logger.info({ config }, 'Workflow configuration');
172
+ this.log(colors.info(`Pipeline mode: ${config.pipeline ? 'enabled' : 'disabled'}`));
173
+ }
174
+ // Execute workflow
175
+ this.log(colors.info('\nStarting workflow orchestration...\n'));
176
+ const result = await this.orchestrator.execute(config);
177
+ // Check for cancellation
178
+ if (this.cancelled) {
179
+ this.log('\n' + colors.warning('Workflow cancelled by user'));
180
+ this.displayFinalSummary(result, config);
181
+ process.exit(130); // Standard interrupted exit code
182
+ }
183
+ // Display final summary
184
+ this.displayFinalSummary(result, config);
185
+ // Exit with appropriate code
186
+ if (!result.overallSuccess) {
187
+ this.error('Workflow completed with failures', { exit: 1 });
188
+ }
189
+ this.log('\n' + colors.success('✓ Workflow completed successfully!'));
190
+ }
191
+ catch (error) {
192
+ this.logger.error({ error: error.message }, 'Workflow command failed');
193
+ // Display user-friendly error
194
+ this.log('\n' + colors.error('✗ Workflow failed:'));
195
+ this.log(colors.error(` ${error.message}`));
196
+ this.error('Workflow execution failed', { exit: 1 });
197
+ }
198
+ }
199
+ /**
200
+ * Display dry-run banner
201
+ *
202
+ * Shows prominent message that workflow is in dry-run mode.
203
+ * @private
204
+ */
205
+ displayDryRunBanner() {
206
+ const banner = formatBox('DRY RUN MODE', 'Actions will be previewed but NOT executed.\nNo files will be created or modified.');
207
+ this.log('\n' + colors.warning(banner));
208
+ }
209
+ /**
210
+ * Display final summary with phase results
211
+ *
212
+ * Shows table with success/failure counts and durations for each phase.
213
+ *
214
+ * @param result - Workflow result with all phase data
215
+ * @param config - Workflow configuration used
216
+ * @private
217
+ */
218
+ // eslint-disable-next-line complexity -- Display method with multiple phases to format
219
+ displayFinalSummary(result, config) {
220
+ this.log('\n' + colors.bold('╔════════════════════════════════════════════════════════╗'));
221
+ this.log(colors.bold('║ Workflow Summary ║'));
222
+ this.log(colors.bold('╚════════════════════════════════════════════════════════╝') + '\n');
223
+ // Build table rows
224
+ const rows = [];
225
+ if (result.epicPhase) {
226
+ const status = result.epicPhase.skipped
227
+ ? colors.dim('Skipped')
228
+ : result.epicPhase.failures.length > 0
229
+ ? colors.error(`${result.epicPhase.failures.length} failed`)
230
+ : colors.success('✓ Complete');
231
+ rows.push([
232
+ 'Epic Creation',
233
+ result.epicPhase.success.toString(),
234
+ result.epicPhase.failures.length.toString(),
235
+ `${(result.epicPhase.duration / 1000).toFixed(1)}s`,
236
+ status,
237
+ ]);
238
+ }
239
+ if (result.storyPhase) {
240
+ const status = result.storyPhase.skipped
241
+ ? colors.dim('Skipped')
242
+ : result.storyPhase.failures.length > 0
243
+ ? colors.error(`${result.storyPhase.failures.length} failed`)
244
+ : colors.success('✓ Complete');
245
+ rows.push([
246
+ 'Story Creation',
247
+ result.storyPhase.success.toString(),
248
+ result.storyPhase.failures.length.toString(),
249
+ `${(result.storyPhase.duration / 1000).toFixed(1)}s`,
250
+ status,
251
+ ]);
252
+ }
253
+ if (result.devPhase) {
254
+ const status = result.devPhase.skipped
255
+ ? colors.dim('Skipped')
256
+ : result.devPhase.failures.length > 0
257
+ ? colors.error(`${result.devPhase.failures.length} failed`)
258
+ : colors.success('✓ Complete');
259
+ rows.push([
260
+ 'Development',
261
+ result.devPhase.success.toString(),
262
+ result.devPhase.failures.length.toString(),
263
+ `${(result.devPhase.duration / 1000).toFixed(1)}s`,
264
+ status,
265
+ ]);
266
+ }
267
+ if (result.qaPhase && !result.qaPhase.skipped) {
268
+ const status = result.qaPhase.failures.length > 0
269
+ ? colors.error(`${result.qaPhase.failures.length} failed`)
270
+ : colors.success('✓ Complete');
271
+ rows.push([
272
+ 'QA Review',
273
+ result.qaPhase.success.toString(),
274
+ result.qaPhase.failures.length.toString(),
275
+ `${(result.qaPhase.duration / 1000).toFixed(1)}s`,
276
+ status,
277
+ ]);
278
+ }
279
+ // Add totals row
280
+ rows.push([
281
+ colors.bold('Total'),
282
+ colors.bold(result.totalFilesProcessed.toString()),
283
+ colors.bold(result.totalFailures.toString()),
284
+ colors.bold(`${(result.totalDuration / 1000).toFixed(1)}s`),
285
+ result.overallSuccess ? colors.success('✓ Success') : colors.error('✗ Failed'),
286
+ ]);
287
+ const table = formatTable(['Phase', 'Success', 'Failed', 'Duration', 'Status'], rows);
288
+ this.log(table);
289
+ // Display failures if any
290
+ if (result.totalFailures > 0) {
291
+ this.log('\n' + colors.error('Failures:'));
292
+ if (result.epicPhase?.failures.length) {
293
+ this.log(colors.error(` Epic Phase:`));
294
+ for (const failure of result.epicPhase.failures) {
295
+ this.log(colors.error(` • ${failure.identifier}: ${failure.error}`));
296
+ }
297
+ }
298
+ if (result.storyPhase?.failures.length) {
299
+ this.log(colors.error(` Story Phase:`));
300
+ for (const failure of result.storyPhase.failures) {
301
+ this.log(colors.error(` • ${failure.identifier}: ${failure.error}`));
302
+ }
303
+ }
304
+ if (result.devPhase?.failures.length) {
305
+ this.log(colors.error(` Development Phase:`));
306
+ for (const failure of result.devPhase.failures) {
307
+ this.log(colors.error(` • ${failure.identifier}: ${failure.error}`));
308
+ }
309
+ }
310
+ if (result.qaPhase?.failures.length) {
311
+ this.log(colors.error(` QA Phase:`));
312
+ for (const failure of result.qaPhase.failures) {
313
+ this.log(colors.error(` • ${failure.identifier}: ${failure.error}`));
314
+ }
315
+ }
316
+ }
317
+ // Dry run reminder
318
+ if (config.dryRun) {
319
+ this.log('\n' + colors.warning('No files were created (dry-run mode)'));
320
+ }
321
+ }
322
+ /**
323
+ * Display phase header with visual separator
324
+ *
325
+ * @param phaseNumber - Current phase number (1-based)
326
+ * @param totalPhases - Total number of phases
327
+ * @param phaseName - Name of the phase
328
+ * @private
329
+ */
330
+ displayPhaseHeader(phaseNumber, totalPhases, phaseName) {
331
+ const header = `Phase ${phaseNumber}/${totalPhases}: ${phaseName}`;
332
+ const separator = '═'.repeat(header.length + 4);
333
+ this.log('\n' + colors.bold(`╔${separator}╗`));
334
+ this.log(colors.bold(`║ ${header} ║`));
335
+ this.log(colors.bold(`╚${separator}╝`) + '\n');
336
+ }
337
+ /**
338
+ * Initialize services and dependencies
339
+ *
340
+ * Creates all service instances needed for workflow orchestration.
341
+ * @param maxConcurrency - Maximum number of concurrent operations
342
+ * @param provider - AI provider to use (claude or gemini)
343
+ * @private
344
+ */
345
+ async initializeServices(maxConcurrency = 3, provider = 'claude') {
346
+ // Create logger
347
+ this.logger = createLogger({ namespace: 'commands:workflow' });
348
+ this.logger.info({ provider }, 'Initializing services with AI provider');
349
+ // Create file system services
350
+ const fileManager = new FileManager(this.logger);
351
+ const pathResolver = new PathResolver(fileManager, this.logger);
352
+ // Create parser services
353
+ const prdParser = new PrdParser(this.logger);
354
+ const epicParser = new EpicParser(this.logger);
355
+ // Create agent runner using factory (supports Claude or Gemini)
356
+ const agentRunner = createAgentRunner(provider, this.logger);
357
+ // Create batch processor with configured concurrency
358
+ const batchProcessor = new BatchProcessor(maxConcurrency, 0, this.logger);
359
+ // Create input detector
360
+ const inputDetector = new InputDetector(fileManager, this.logger);
361
+ // Create story type detector for auto-documentation
362
+ const storyTypeDetector = new StoryTypeDetector(this.logger);
363
+ // Create orchestrator
364
+ this.orchestrator = new WorkflowOrchestrator({
365
+ agentRunner,
366
+ batchProcessor,
367
+ epicParser,
368
+ fileManager,
369
+ inputDetector,
370
+ logger: this.logger,
371
+ pathResolver,
372
+ prdParser,
373
+ storyTypeDetector,
374
+ });
375
+ this.logger.info({ provider }, 'Services initialized successfully');
376
+ }
377
+ /**
378
+ * Register SIGINT handler for graceful cancellation
379
+ *
380
+ * Allows user to cancel workflow with Ctrl+C, completing current operation first.
381
+ * @private
382
+ */
383
+ registerSignalHandlers() {
384
+ process.on('SIGINT', () => {
385
+ this.cancelled = true;
386
+ this.logger.warn('Cancellation requested... completing current operation');
387
+ this.log('\n' + colors.warning('⚠️ Cancellation requested... completing current operation'));
388
+ });
389
+ }
390
+ }
@@ -0,0 +1 @@
1
+ export { run } from '@oclif/core';
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ export { run } from '@oclif/core';
@@ -0,0 +1,50 @@
1
+ import type { AgentResult } from './agent-result.js';
2
+ /**
3
+ * Available BMAD agent types
4
+ */
5
+ export type AgentType = 'analyst' | 'architect' | 'dev' | 'pm' | 'prd-fixer' | 'quick-flow-solo-dev' | 'sm' | 'tea' | 'tech-writer' | 'ux-designer';
6
+ /**
7
+ * Agent options without prompt and callbacks (used internally)
8
+ */
9
+ export type AgentOptionsWithoutPrompt = Omit<AgentOptions, 'onPrompt' | 'onResponse' | 'prompt'>;
10
+ /**
11
+ * Callback invoked when a prompt is about to be sent to Claude
12
+ */
13
+ export type OnPromptCallback = (prompt: string, options: AgentOptionsWithoutPrompt) => Promise<void> | void;
14
+ /**
15
+ * Callback invoked when a response is received from Claude
16
+ */
17
+ export type OnResponseCallback = (result: AgentResult) => Promise<void> | void;
18
+ /**
19
+ * Options for executing a Claude AI agent
20
+ */
21
+ export interface AgentOptions {
22
+ /**
23
+ * The type of agent to execute
24
+ */
25
+ agentType: AgentType;
26
+ /**
27
+ * Additional CLI flags to pass to the Claude executable
28
+ */
29
+ flags?: string[];
30
+ /**
31
+ * Callback invoked when prompt is sent (for logging)
32
+ */
33
+ onPrompt?: OnPromptCallback;
34
+ /**
35
+ * Callback invoked when response is received (for logging)
36
+ */
37
+ onResponse?: OnResponseCallback;
38
+ /**
39
+ * The prompt to execute with the agent
40
+ */
41
+ prompt: string;
42
+ /**
43
+ * File references to include in the agent execution
44
+ */
45
+ references?: string[];
46
+ /**
47
+ * Timeout in milliseconds (default: 1800000ms = 30 minutes)
48
+ */
49
+ timeout?: number;
50
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Result of executing a Claude AI agent
3
+ */
4
+ export interface AgentResult {
5
+ /**
6
+ * The type of agent that was executed
7
+ */
8
+ agentType: string;
9
+ /**
10
+ * Execution duration in milliseconds
11
+ */
12
+ duration: number;
13
+ /**
14
+ * Error messages from stderr
15
+ */
16
+ errors: string;
17
+ /**
18
+ * The process exit code
19
+ */
20
+ exitCode: number;
21
+ /**
22
+ * The output from stdout
23
+ */
24
+ output: string;
25
+ /**
26
+ * Whether the agent execution was successful
27
+ */
28
+ success: boolean;
29
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Model exports
3
+ */
4
+ export * from './agent-options.js';
5
+ export * from './agent-result.js';
6
+ export * from './phase-result.js';
7
+ export * from './provider.js';
8
+ export * from './story.js';
9
+ export * from './workflow-config.js';
10
+ export * from './workflow-result.js';
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Model exports
3
+ */
4
+ export * from './agent-options.js';
5
+ export * from './agent-result.js';
6
+ export * from './phase-result.js';
7
+ export * from './provider.js';
8
+ export * from './story.js';
9
+ export * from './workflow-config.js';
10
+ export * from './workflow-result.js';
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Phase Result
3
+ *
4
+ * Represents the result of executing a single workflow phase
5
+ * (epic creation, story creation, or development).
6
+ */
7
+ /**
8
+ * Result of a single workflow phase execution
9
+ *
10
+ * Tracks successes, failures, and execution metrics for a phase.
11
+ * Phases include epic creation, story creation, and development.
12
+ */
13
+ export interface PhaseResult {
14
+ /**
15
+ * Execution time in milliseconds
16
+ *
17
+ * Time from phase start to phase completion.
18
+ */
19
+ duration: number;
20
+ /**
21
+ * Details of failed operations
22
+ *
23
+ * Empty array if all operations succeeded.
24
+ */
25
+ failures: PhaseFailure[];
26
+ /**
27
+ * Name of the phase that was executed
28
+ *
29
+ * One of: 'epic', 'story', 'dev'
30
+ */
31
+ phaseName: string;
32
+ /**
33
+ * Phase was skipped
34
+ *
35
+ * True if phase was skipped due to flag (skipEpics, skipStories, skipDev)
36
+ * or due to input type (e.g., starting from epic file skips epic phase).
37
+ * @default false
38
+ */
39
+ skipped: boolean;
40
+ /**
41
+ * Count of successful operations in this phase
42
+ *
43
+ * For epic phase: number of epics created successfully
44
+ * For story phase: number of stories created successfully
45
+ * For dev phase: number of stories developed successfully
46
+ */
47
+ success: number;
48
+ }
49
+ /**
50
+ * Details of a single failure within a phase
51
+ */
52
+ export interface PhaseFailure {
53
+ /**
54
+ * Error message describing the failure
55
+ */
56
+ error: string;
57
+ /**
58
+ * Identifier for the failed operation
59
+ *
60
+ * For epic phase: epic number (e.g., '1', '2')
61
+ * For story phase: story number (e.g., '1.1', '2.3')
62
+ * For dev phase: story file path
63
+ */
64
+ identifier: string;
65
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Phase Result
3
+ *
4
+ * Represents the result of executing a single workflow phase
5
+ * (epic creation, story creation, or development).
6
+ */
7
+ export {};