@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,142 @@
1
+ /**
2
+ * Task Graph System Types
3
+ * Defines the structure for decomposing large goals into executable task graphs
4
+ */
5
+ /**
6
+ * Individual task node in the dependency graph
7
+ */
8
+ export interface TaskNode {
9
+ /** Optional: Agent type to use (dev, architect, qa, etc.) */
10
+ agentType?: string;
11
+ /** Array of task IDs that must complete before this task can start */
12
+ dependencies: string[];
13
+ /** Detailed description of what this task accomplishes */
14
+ description: string;
15
+ /** Estimated time in minutes for Claude agent to complete */
16
+ estimatedMinutes: number;
17
+ /** Unique task identifier (e.g., "task-001") */
18
+ id: string;
19
+ /** File path where task output will be written */
20
+ outputFile: string;
21
+ /** Whether this task can run in parallel with other tasks in the same layer */
22
+ parallelizable: boolean;
23
+ /** Full prompt for the agent to execute this task */
24
+ prompt: string;
25
+ /** Optional: Specific files this task operates on (for per-file tasks) */
26
+ targetFiles?: string[];
27
+ /** Human-readable task title */
28
+ title: string;
29
+ }
30
+ /**
31
+ * Complete task graph representing a decomposed goal
32
+ */
33
+ export interface TaskGraph {
34
+ /** The original big goal being decomposed */
35
+ goal: string;
36
+ /** Master prompt template reusable across similar goals */
37
+ masterPrompt: string;
38
+ /** Metadata about the task graph */
39
+ metadata: TaskGraphMetadata;
40
+ /** Session-specific information */
41
+ session: {
42
+ createdAt: string;
43
+ id: string;
44
+ outputDirectory: string;
45
+ };
46
+ /** Array of all tasks in the graph */
47
+ tasks: TaskNode[];
48
+ }
49
+ /**
50
+ * Metadata about the task graph
51
+ */
52
+ export interface TaskGraphMetadata {
53
+ /** Estimated total duration in minutes */
54
+ estimatedDuration: number;
55
+ /** Execution layers (each layer runs in parallel, layers run sequentially) */
56
+ executionLayers: string[][];
57
+ /** Maximum number of tasks that can run in parallel */
58
+ maxParallelism: number;
59
+ /** Whether per-file task generation was used */
60
+ perFileMode: boolean;
61
+ /** Whether tasks are formatted as BMAD stories */
62
+ storyFormat?: boolean;
63
+ /** Optional: Total files targeted for per-file mode */
64
+ totalFiles?: number;
65
+ /** Total number of tasks */
66
+ totalTasks: number;
67
+ }
68
+ /**
69
+ * Result of executing a single task
70
+ */
71
+ export interface TaskExecutionResult {
72
+ duration: number;
73
+ errors?: string;
74
+ exitCode: number;
75
+ output: string;
76
+ success: boolean;
77
+ taskId: string;
78
+ }
79
+ /**
80
+ * Result of executing entire task graph
81
+ */
82
+ export interface GraphExecutionResult {
83
+ completedTasks: number;
84
+ executionSummary: {
85
+ layerResults: LayerExecutionResult[];
86
+ };
87
+ failedTasks: number;
88
+ skippedTasks: number;
89
+ success: boolean;
90
+ taskResults: TaskExecutionResult[];
91
+ totalDuration: number;
92
+ totalTasks: number;
93
+ }
94
+ /**
95
+ * Result of executing a single layer
96
+ */
97
+ export interface LayerExecutionResult {
98
+ duration: number;
99
+ layerIndex: number;
100
+ parallelTasksExecuted: number;
101
+ success: boolean;
102
+ taskIds: string[];
103
+ }
104
+ /**
105
+ * Options for task decomposition
106
+ */
107
+ export interface DecomposeOptions {
108
+ /** BMAD agent to use for planning/decomposition */
109
+ agent?: string;
110
+ /** Optional context files to provide to the planner */
111
+ contextFiles?: string[];
112
+ /** Working directory for task execution */
113
+ cwd?: string;
114
+ /** Execute immediately without confirmation */
115
+ execute?: boolean;
116
+ /** File glob pattern for per-file mode (e.g., "src/*.js") */
117
+ filePattern?: string;
118
+ /** The big goal to decompose */
119
+ goal: string;
120
+ /** Maximum number of tasks to run in parallel */
121
+ maxParallel?: number;
122
+ /** Enable per-file task generation for file-heavy operations */
123
+ perFile?: boolean;
124
+ /** Plan only without executing */
125
+ planOnly?: boolean;
126
+ /** Format tasks as proper BMAD stories instead of simple tasks */
127
+ storyFormat?: boolean;
128
+ /** Project prefix for story IDs (e.g., "MIGRATE", "REFACTOR") - required when storyFormat is true */
129
+ storyPrefix?: string;
130
+ /** Timeout per task in milliseconds */
131
+ taskTimeout?: number;
132
+ }
133
+ /**
134
+ * Configuration for the decompose session
135
+ */
136
+ export interface DecomposeSessionConfig {
137
+ createdAt: Date;
138
+ goal: string;
139
+ options: DecomposeOptions;
140
+ outputDir: string;
141
+ sessionId: string;
142
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Task Graph System Types
3
+ * Defines the structure for decomposing large goals into executable task graphs
4
+ */
5
+ export {};
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Format a success message with green color and checkmark icon
3
+ *
4
+ * @param text - Message text to format
5
+ * @returns Formatted string with ANSI color codes and ✓ icon
6
+ */
7
+ export declare const success: (text: string) => string;
8
+ /**
9
+ * Format an error message with red color and X icon
10
+ *
11
+ * @param text - Message text to format
12
+ * @returns Formatted string with ANSI color codes and ✗ icon
13
+ */
14
+ export declare const error: (text: string) => string;
15
+ /**
16
+ * Format a warning message with yellow color and warning icon
17
+ *
18
+ * @param text - Message text to format
19
+ * @returns Formatted string with ANSI color codes and ⚠ icon
20
+ */
21
+ export declare const warning: (text: string) => string;
22
+ /**
23
+ * Format an info message with blue color and info icon
24
+ *
25
+ * @param text - Message text to format
26
+ * @returns Formatted string with ANSI color codes and ℹ icon
27
+ */
28
+ export declare const info: (text: string) => string;
29
+ /**
30
+ * Highlight text with cyan color for emphasis
31
+ *
32
+ * @param text - Text to highlight
33
+ * @returns Formatted string with ANSI color codes
34
+ */
35
+ export declare const highlight: (text: string) => string;
36
+ /**
37
+ * Format text in bold style
38
+ *
39
+ * @param text - Text to make bold
40
+ * @returns Formatted string with ANSI bold codes
41
+ */
42
+ export declare const bold: (text: string) => string;
43
+ /**
44
+ * Format text in dim style (lower intensity)
45
+ *
46
+ * @param text - Text to dim
47
+ * @returns Formatted string with ANSI dim codes
48
+ */
49
+ export declare const dim: (text: string) => string;
@@ -0,0 +1,50 @@
1
+ import chalk from 'chalk';
2
+ /**
3
+ * Format a success message with green color and checkmark icon
4
+ *
5
+ * @param text - Message text to format
6
+ * @returns Formatted string with ANSI color codes and ✓ icon
7
+ */
8
+ export const success = (text) => chalk.green(`✓ ${text}`);
9
+ /**
10
+ * Format an error message with red color and X icon
11
+ *
12
+ * @param text - Message text to format
13
+ * @returns Formatted string with ANSI color codes and ✗ icon
14
+ */
15
+ export const error = (text) => chalk.red(`✗ ${text}`);
16
+ /**
17
+ * Format a warning message with yellow color and warning icon
18
+ *
19
+ * @param text - Message text to format
20
+ * @returns Formatted string with ANSI color codes and ⚠ icon
21
+ */
22
+ export const warning = (text) => chalk.yellow(`⚠ ${text}`);
23
+ /**
24
+ * Format an info message with blue color and info icon
25
+ *
26
+ * @param text - Message text to format
27
+ * @returns Formatted string with ANSI color codes and ℹ icon
28
+ */
29
+ export const info = (text) => chalk.blue(`ℹ ${text}`);
30
+ /**
31
+ * Highlight text with cyan color for emphasis
32
+ *
33
+ * @param text - Text to highlight
34
+ * @returns Formatted string with ANSI color codes
35
+ */
36
+ export const highlight = (text) => chalk.cyan(text);
37
+ /**
38
+ * Format text in bold style
39
+ *
40
+ * @param text - Text to make bold
41
+ * @returns Formatted string with ANSI bold codes
42
+ */
43
+ export const bold = (text) => chalk.bold(text);
44
+ /**
45
+ * Format text in dim style (lower intensity)
46
+ *
47
+ * @param text - Text to dim
48
+ * @returns Formatted string with ANSI dim codes
49
+ */
50
+ export const dim = (text) => chalk.dim(text);
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Error Formatter Utility
3
+ *
4
+ * Provides functions to format errors into user-friendly messages with
5
+ * actionable suggestions and colored output.
6
+ */
7
+ /**
8
+ * Options for error formatting
9
+ */
10
+ export interface FormatErrorOptions {
11
+ /**
12
+ * Use colored output
13
+ * @default true
14
+ */
15
+ colored?: boolean;
16
+ /**
17
+ * Include error code in output
18
+ * @default true
19
+ */
20
+ showCode?: boolean;
21
+ /**
22
+ * Include stack trace in output
23
+ * @default false
24
+ */
25
+ verbose?: boolean;
26
+ }
27
+ /**
28
+ * Format an error into a user-friendly message
29
+ *
30
+ * Converts errors into plain English with actionable suggestions.
31
+ * Supports custom error types with specific formatting.
32
+ *
33
+ * @param error - Error to format
34
+ * @param options - Formatting options
35
+ * @returns Formatted error message
36
+ * @example
37
+ * const message = formatError(error, { verbose: true })
38
+ * console.error(message)
39
+ */
40
+ export declare function formatError(error: Error, options?: FormatErrorOptions): string;
41
+ /**
42
+ * Format error with stack trace for verbose logging
43
+ *
44
+ * This is a convenience function that always includes the stack trace.
45
+ *
46
+ * @param error - Error to format
47
+ * @returns Formatted error message with stack trace
48
+ * @example
49
+ * const message = formatErrorVerbose(error)
50
+ * console.error(message)
51
+ */
52
+ export declare function formatErrorVerbose(error: Error): string;
53
+ /**
54
+ * Format error for plain text output without colors
55
+ *
56
+ * Useful for logging to files or non-terminal outputs.
57
+ *
58
+ * @param error - Error to format
59
+ * @returns Formatted error message without colors
60
+ * @example
61
+ * const message = formatErrorPlain(error)
62
+ * fs.writeFileSync('error.log', message)
63
+ */
64
+ export declare function formatErrorPlain(error: Error): string;
@@ -0,0 +1,279 @@
1
+ /**
2
+ * Error Formatter Utility
3
+ *
4
+ * Provides functions to format errors into user-friendly messages with
5
+ * actionable suggestions and colored output.
6
+ */
7
+ import chalk from 'chalk';
8
+ import { AgentError, BaseError, ConfigurationError, FileSystemError, ParserError, ValidationError } from './errors.js';
9
+ /**
10
+ * Format an error into a user-friendly message
11
+ *
12
+ * Converts errors into plain English with actionable suggestions.
13
+ * Supports custom error types with specific formatting.
14
+ *
15
+ * @param error - Error to format
16
+ * @param options - Formatting options
17
+ * @returns Formatted error message
18
+ * @example
19
+ * const message = formatError(error, { verbose: true })
20
+ * console.error(message)
21
+ */
22
+ export function formatError(error, options = {}) {
23
+ const { colored = true, showCode = true, verbose = false } = options;
24
+ // Use chalk or plain text based on colored option
25
+ const errorStyle = colored ? chalk.red.bold : (text) => text;
26
+ const warningStyle = colored ? chalk.yellow : (text) => text;
27
+ const contextStyle = colored ? chalk.gray : (text) => text;
28
+ let message = '';
29
+ // Add error indicator
30
+ message += `${errorStyle('✗')} ${errorStyle('Error')}: `;
31
+ // Format based on error type
32
+ message += getFormattedErrorMessage(error, { colored });
33
+ // Add suggestion if available
34
+ if (error instanceof BaseError && error.suggestion) {
35
+ message += `\n${warningStyle('💡 Suggestion:')} ${error.suggestion}`;
36
+ }
37
+ // Add error code if requested
38
+ if (showCode && error instanceof BaseError) {
39
+ message += `\n${contextStyle(`[${error.code}]`)}`;
40
+ }
41
+ // Add context information
42
+ if (error instanceof BaseError && error.context) {
43
+ message += `\n${contextStyle('Context:')} ${formatContext(error.context, { colored })}`;
44
+ }
45
+ // Add stack trace in verbose mode
46
+ if (verbose && error.stack) {
47
+ message += `\n\n${contextStyle('Stack Trace:')}\n${contextStyle(error.stack)}`;
48
+ }
49
+ return message;
50
+ }
51
+ /**
52
+ * Get formatted error message based on error type
53
+ *
54
+ * @param error - Error to format
55
+ * @param options - Formatting options
56
+ * @param options.colored - Whether to use colored output
57
+ * @returns Formatted error message
58
+ * @private
59
+ */
60
+ function getFormattedErrorMessage(error, options) {
61
+ if (error instanceof ValidationError) {
62
+ return formatValidationError(error, options);
63
+ }
64
+ if (error instanceof FileSystemError) {
65
+ return formatFileSystemError(error, options);
66
+ }
67
+ if (error instanceof AgentError) {
68
+ return formatAgentError(error, options);
69
+ }
70
+ if (error instanceof ConfigurationError) {
71
+ return formatConfigurationError(error, options);
72
+ }
73
+ if (error instanceof ParserError) {
74
+ return formatParserError(error, options);
75
+ }
76
+ if (error instanceof BaseError) {
77
+ return formatBaseError(error, options);
78
+ }
79
+ return error.message;
80
+ }
81
+ /**
82
+ * Format a validation error with specific suggestions
83
+ *
84
+ * @param error - ValidationError to format
85
+ * @param options - Formatting options
86
+ * @param options.colored - Whether to use colored output
87
+ * @returns Formatted error message
88
+ * @private
89
+ */
90
+ function formatValidationError(error, options) {
91
+ const suggestStyle = options.colored ? chalk.yellow : (text) => text;
92
+ let { message } = error;
93
+ // Add field-specific suggestions
94
+ if (error.context?.field) {
95
+ message += `\n${suggestStyle('→')} Field: ${error.context.field}`;
96
+ }
97
+ // Add generic validation suggestion
98
+ message += `\n${suggestStyle('→')} Check your input and try again.`;
99
+ return message;
100
+ }
101
+ /**
102
+ * Format a file system error with path information
103
+ *
104
+ * @param error - FileSystemError to format
105
+ * @param options - Formatting options
106
+ * @param options.colored - Whether to use colored output
107
+ * @returns Formatted error message
108
+ * @private
109
+ */
110
+ function formatFileSystemError(error, options) {
111
+ const suggestStyle = options.colored ? chalk.yellow : (text) => text;
112
+ const pathStyle = options.colored ? chalk.cyan : (text) => text;
113
+ let { message } = error;
114
+ // Add file path if available
115
+ if (error.context?.filePath) {
116
+ message += `\n${suggestStyle('→')} Path: ${pathStyle(error.context.filePath)}`;
117
+ }
118
+ // Add suggestions based on error message
119
+ if (error.message.includes('not found') || error.message.includes('ENOENT')) {
120
+ message += `\n${suggestStyle('→')} Check the path and ensure the file exists.`;
121
+ message += `\n${suggestStyle('→')} Verify your current working directory.`;
122
+ }
123
+ else if (error.message.includes('permission') || error.message.includes('EACCES')) {
124
+ message += `\n${suggestStyle('→')} Check file permissions.`;
125
+ message += `\n${suggestStyle('→')} Ensure you have write access to the directory.`;
126
+ }
127
+ else {
128
+ message += `\n${suggestStyle('→')} Check the path and file permissions.`;
129
+ }
130
+ return message;
131
+ }
132
+ /**
133
+ * Format an agent error with execution details
134
+ *
135
+ * @param error - AgentError to format
136
+ * @param options - Formatting options
137
+ * @param options.colored - Whether to use colored output
138
+ * @returns Formatted error message
139
+ * @private
140
+ */
141
+ function formatAgentError(error, options) {
142
+ const suggestStyle = options.colored ? chalk.yellow : (text) => text;
143
+ const codeStyle = options.colored ? chalk.cyan : (text) => text;
144
+ let { message } = error;
145
+ // Add exit code if available
146
+ if (error.context?.exitCode !== undefined) {
147
+ message += `\n${suggestStyle('→')} Exit code: ${codeStyle(String(error.context.exitCode))}`;
148
+ }
149
+ // Add stderr if available
150
+ if (error.context?.stderr) {
151
+ const stderr = String(error.context.stderr).trim();
152
+ if (stderr) {
153
+ message += `\n${suggestStyle('→')} Error output: ${stderr.slice(0, 200)}`;
154
+ }
155
+ }
156
+ // Add agent type if available
157
+ if (error.context?.agentType) {
158
+ message += `\n${suggestStyle('→')} Agent: ${error.context.agentType}`;
159
+ }
160
+ // Add suggestions
161
+ message += `\n${suggestStyle('→')} Check Claude CLI installation and authentication.`;
162
+ message += `\n${suggestStyle('→')} Verify the agent prompt and arguments.`;
163
+ return message;
164
+ }
165
+ /**
166
+ * Format a configuration error with field information
167
+ *
168
+ * @param error - ConfigurationError to format
169
+ * @param options - Formatting options
170
+ * @param options.colored - Whether to use colored output
171
+ * @returns Formatted error message
172
+ * @private
173
+ */
174
+ function formatConfigurationError(error, options) {
175
+ const suggestStyle = options.colored ? chalk.yellow : (text) => text;
176
+ const fieldStyle = options.colored ? chalk.cyan : (text) => text;
177
+ let { message } = error;
178
+ // Add field information
179
+ if (error.context?.field) {
180
+ message += `\n${suggestStyle('→')} Field: ${fieldStyle(error.context.field)}`;
181
+ }
182
+ // Add expected value if available
183
+ if (error.context?.expected) {
184
+ message += `\n${suggestStyle('→')} Expected: ${error.context.expected}`;
185
+ }
186
+ // Add suggestions
187
+ message += `\n${suggestStyle('→')} Check .bmad-core/core-config.yaml for correct configuration.`;
188
+ message += `\n${suggestStyle('→')} Run 'bmad-workflow config validate' for detailed validation.`;
189
+ return message;
190
+ }
191
+ /**
192
+ * Format a parser error with line information
193
+ *
194
+ * @param error - ParserError to format
195
+ * @param options - Formatting options
196
+ * @param options.colored - Whether to use colored output
197
+ * @returns Formatted error message
198
+ * @private
199
+ */
200
+ function formatParserError(error, options) {
201
+ const suggestStyle = options.colored ? chalk.yellow : (text) => text;
202
+ const lineStyle = options.colored ? chalk.cyan : (text) => text;
203
+ let { message } = error;
204
+ // Add file path if available
205
+ if (error.context?.filePath) {
206
+ message += `\n${suggestStyle('→')} File: ${error.context.filePath}`;
207
+ }
208
+ // Add line number if available
209
+ if (error.context?.line !== undefined) {
210
+ message += `\n${suggestStyle('→')} Line: ${lineStyle(String(error.context.line))}`;
211
+ }
212
+ // Add expected format if available
213
+ if (error.context?.expectedFormat) {
214
+ message += `\n${suggestStyle('→')} Expected format: ${error.context.expectedFormat}`;
215
+ }
216
+ // Add generic parsing suggestion
217
+ message += `\n${suggestStyle('→')} Check the file format against documentation.`;
218
+ message += `\n${suggestStyle('→')} Ensure proper markdown structure.`;
219
+ return message;
220
+ }
221
+ /**
222
+ * Format a base error
223
+ *
224
+ * @param error - BaseError to format
225
+ * @param _options - Formatting options (not used but required for interface consistency)
226
+ * @param _options.colored - Whether to use colored output (not used)
227
+ * @returns Formatted error message
228
+ * @private
229
+ */
230
+ function formatBaseError(error, _options) {
231
+ return error.message;
232
+ }
233
+ /**
234
+ * Format error context object into readable string
235
+ *
236
+ * @param context - Context object to format
237
+ * @param options - Formatting options
238
+ * @param options.colored - Whether to use colored output
239
+ * @returns Formatted context string
240
+ * @private
241
+ */
242
+ function formatContext(context, options) {
243
+ const keyStyle = options.colored ? chalk.cyan : (text) => text;
244
+ return Object.entries(context)
245
+ .filter(([key]) => key !== 'stderr' && key !== 'exitCode' && key !== 'agentType') // Skip already formatted fields
246
+ .map(([key, value]) => {
247
+ const valueStr = typeof value === 'object' ? JSON.stringify(value) : String(value);
248
+ return `${keyStyle(key)}: ${valueStr}`;
249
+ })
250
+ .join(', ');
251
+ }
252
+ /**
253
+ * Format error with stack trace for verbose logging
254
+ *
255
+ * This is a convenience function that always includes the stack trace.
256
+ *
257
+ * @param error - Error to format
258
+ * @returns Formatted error message with stack trace
259
+ * @example
260
+ * const message = formatErrorVerbose(error)
261
+ * console.error(message)
262
+ */
263
+ export function formatErrorVerbose(error) {
264
+ return formatError(error, { verbose: true });
265
+ }
266
+ /**
267
+ * Format error for plain text output without colors
268
+ *
269
+ * Useful for logging to files or non-terminal outputs.
270
+ *
271
+ * @param error - Error to format
272
+ * @returns Formatted error message without colors
273
+ * @example
274
+ * const message = formatErrorPlain(error)
275
+ * fs.writeFileSync('error.log', message)
276
+ */
277
+ export function formatErrorPlain(error) {
278
+ return formatError(error, { colored: false });
279
+ }