wogiflow 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (221) hide show
  1. package/.workflow/agents/reviewer.md +81 -0
  2. package/.workflow/agents/security.md +94 -0
  3. package/.workflow/agents/story-writer.md +58 -0
  4. package/.workflow/bridges/base-bridge.js +395 -0
  5. package/.workflow/bridges/claude-bridge.js +434 -0
  6. package/.workflow/bridges/index.js +130 -0
  7. package/.workflow/lib/assumption-detector.js +481 -0
  8. package/.workflow/lib/config-substitution.js +371 -0
  9. package/.workflow/lib/failure-categories.js +478 -0
  10. package/.workflow/state/app-map.md.template +15 -0
  11. package/.workflow/state/architecture.md.template +24 -0
  12. package/.workflow/state/component-index.json.template +5 -0
  13. package/.workflow/state/decisions.md.template +15 -0
  14. package/.workflow/state/feedback-patterns.md.template +9 -0
  15. package/.workflow/state/knowledge-sync.json.template +6 -0
  16. package/.workflow/state/progress.md.template +14 -0
  17. package/.workflow/state/ready.json.template +7 -0
  18. package/.workflow/state/request-log.md.template +14 -0
  19. package/.workflow/state/session-state.json.template +11 -0
  20. package/.workflow/state/stack.md.template +33 -0
  21. package/.workflow/state/testing.md.template +36 -0
  22. package/.workflow/templates/claude-md.hbs +257 -0
  23. package/.workflow/templates/correction-report.md +67 -0
  24. package/.workflow/templates/gemini-md.hbs +52 -0
  25. package/README.md +1802 -0
  26. package/bin/flow +205 -0
  27. package/lib/index.js +33 -0
  28. package/lib/installer.js +467 -0
  29. package/lib/release-channel.js +269 -0
  30. package/lib/skill-registry.js +526 -0
  31. package/lib/upgrader.js +401 -0
  32. package/lib/utils.js +305 -0
  33. package/package.json +64 -0
  34. package/scripts/flow +985 -0
  35. package/scripts/flow-adaptive-learning.js +1259 -0
  36. package/scripts/flow-aggregate.js +488 -0
  37. package/scripts/flow-archive +133 -0
  38. package/scripts/flow-auto-context.js +1015 -0
  39. package/scripts/flow-auto-learn.js +615 -0
  40. package/scripts/flow-bridge.js +223 -0
  41. package/scripts/flow-browser-suggest.js +316 -0
  42. package/scripts/flow-bug.js +247 -0
  43. package/scripts/flow-cascade.js +711 -0
  44. package/scripts/flow-changelog +85 -0
  45. package/scripts/flow-checkpoint.js +483 -0
  46. package/scripts/flow-cli.js +403 -0
  47. package/scripts/flow-code-intelligence.js +760 -0
  48. package/scripts/flow-complexity.js +502 -0
  49. package/scripts/flow-config-set.js +152 -0
  50. package/scripts/flow-constants.js +157 -0
  51. package/scripts/flow-context +152 -0
  52. package/scripts/flow-context-init.js +482 -0
  53. package/scripts/flow-context-monitor.js +384 -0
  54. package/scripts/flow-context-scoring.js +886 -0
  55. package/scripts/flow-correct.js +458 -0
  56. package/scripts/flow-damage-control.js +985 -0
  57. package/scripts/flow-deps +101 -0
  58. package/scripts/flow-diff.js +700 -0
  59. package/scripts/flow-done +151 -0
  60. package/scripts/flow-done.js +489 -0
  61. package/scripts/flow-durable-session.js +1541 -0
  62. package/scripts/flow-entropy-monitor.js +345 -0
  63. package/scripts/flow-export-profile +349 -0
  64. package/scripts/flow-export-scanner.js +1046 -0
  65. package/scripts/flow-figma-confirm.js +400 -0
  66. package/scripts/flow-figma-extract.js +496 -0
  67. package/scripts/flow-figma-generate.js +683 -0
  68. package/scripts/flow-figma-index.js +909 -0
  69. package/scripts/flow-figma-match.js +617 -0
  70. package/scripts/flow-figma-mcp-server.js +518 -0
  71. package/scripts/flow-figma-pipeline.js +414 -0
  72. package/scripts/flow-file-ops.js +301 -0
  73. package/scripts/flow-gate-confidence.js +825 -0
  74. package/scripts/flow-guided-edit.js +659 -0
  75. package/scripts/flow-health +185 -0
  76. package/scripts/flow-health.js +413 -0
  77. package/scripts/flow-hooks.js +556 -0
  78. package/scripts/flow-http-client.js +249 -0
  79. package/scripts/flow-hybrid-detect.js +167 -0
  80. package/scripts/flow-hybrid-interactive.js +591 -0
  81. package/scripts/flow-hybrid-test.js +152 -0
  82. package/scripts/flow-import-profile +439 -0
  83. package/scripts/flow-init +253 -0
  84. package/scripts/flow-instruction-richness.js +827 -0
  85. package/scripts/flow-jira-integration.js +579 -0
  86. package/scripts/flow-knowledge-router.js +522 -0
  87. package/scripts/flow-knowledge-sync.js +589 -0
  88. package/scripts/flow-linear-integration.js +631 -0
  89. package/scripts/flow-links.js +774 -0
  90. package/scripts/flow-log-manager.js +559 -0
  91. package/scripts/flow-loop-enforcer.js +1246 -0
  92. package/scripts/flow-loop-retry-learning.js +630 -0
  93. package/scripts/flow-lsp.js +923 -0
  94. package/scripts/flow-map-index +348 -0
  95. package/scripts/flow-map-sync +201 -0
  96. package/scripts/flow-memory-blocks.js +668 -0
  97. package/scripts/flow-memory-compactor.js +350 -0
  98. package/scripts/flow-memory-db.js +1110 -0
  99. package/scripts/flow-memory-sync.js +484 -0
  100. package/scripts/flow-metrics.js +353 -0
  101. package/scripts/flow-migrate-ids.js +370 -0
  102. package/scripts/flow-model-adapter.js +802 -0
  103. package/scripts/flow-model-router.js +884 -0
  104. package/scripts/flow-models.js +1231 -0
  105. package/scripts/flow-morning.js +517 -0
  106. package/scripts/flow-multi-approach.js +660 -0
  107. package/scripts/flow-new-feature +86 -0
  108. package/scripts/flow-onboard +1042 -0
  109. package/scripts/flow-orchestrate-llm.js +459 -0
  110. package/scripts/flow-orchestrate.js +3592 -0
  111. package/scripts/flow-output.js +123 -0
  112. package/scripts/flow-parallel-detector.js +399 -0
  113. package/scripts/flow-parallel-dispatch.js +987 -0
  114. package/scripts/flow-parallel.js +428 -0
  115. package/scripts/flow-pattern-enforcer.js +600 -0
  116. package/scripts/flow-prd-manager.js +282 -0
  117. package/scripts/flow-progress.js +323 -0
  118. package/scripts/flow-project-analyzer.js +975 -0
  119. package/scripts/flow-prompt-composer.js +487 -0
  120. package/scripts/flow-providers.js +1381 -0
  121. package/scripts/flow-queue.js +308 -0
  122. package/scripts/flow-ready +82 -0
  123. package/scripts/flow-ready.js +189 -0
  124. package/scripts/flow-regression.js +396 -0
  125. package/scripts/flow-response-parser.js +450 -0
  126. package/scripts/flow-resume.js +284 -0
  127. package/scripts/flow-rules-sync.js +439 -0
  128. package/scripts/flow-run-trace.js +718 -0
  129. package/scripts/flow-safety.js +587 -0
  130. package/scripts/flow-search +104 -0
  131. package/scripts/flow-security.js +481 -0
  132. package/scripts/flow-session-end +106 -0
  133. package/scripts/flow-session-end.js +437 -0
  134. package/scripts/flow-session-state.js +671 -0
  135. package/scripts/flow-setup-hooks +216 -0
  136. package/scripts/flow-setup-hooks.js +377 -0
  137. package/scripts/flow-skill-create.js +329 -0
  138. package/scripts/flow-skill-creator.js +572 -0
  139. package/scripts/flow-skill-generator.js +1046 -0
  140. package/scripts/flow-skill-learn.js +880 -0
  141. package/scripts/flow-skill-matcher.js +578 -0
  142. package/scripts/flow-spec-generator.js +820 -0
  143. package/scripts/flow-stack-wizard.js +895 -0
  144. package/scripts/flow-standup +162 -0
  145. package/scripts/flow-start +74 -0
  146. package/scripts/flow-start.js +235 -0
  147. package/scripts/flow-status +110 -0
  148. package/scripts/flow-status.js +301 -0
  149. package/scripts/flow-step-browser.js +83 -0
  150. package/scripts/flow-step-changelog.js +217 -0
  151. package/scripts/flow-step-comments.js +306 -0
  152. package/scripts/flow-step-complexity.js +234 -0
  153. package/scripts/flow-step-coverage.js +218 -0
  154. package/scripts/flow-step-knowledge.js +193 -0
  155. package/scripts/flow-step-pr-tests.js +364 -0
  156. package/scripts/flow-step-regression.js +89 -0
  157. package/scripts/flow-step-review.js +516 -0
  158. package/scripts/flow-step-security.js +162 -0
  159. package/scripts/flow-step-silent-failures.js +290 -0
  160. package/scripts/flow-step-simplifier.js +346 -0
  161. package/scripts/flow-story +105 -0
  162. package/scripts/flow-story.js +500 -0
  163. package/scripts/flow-suspend.js +252 -0
  164. package/scripts/flow-sync-daemon.js +654 -0
  165. package/scripts/flow-task-analyzer.js +606 -0
  166. package/scripts/flow-team-dashboard.js +748 -0
  167. package/scripts/flow-team-sync.js +752 -0
  168. package/scripts/flow-team.js +977 -0
  169. package/scripts/flow-tech-options.js +528 -0
  170. package/scripts/flow-templates.js +812 -0
  171. package/scripts/flow-tiered-learning.js +728 -0
  172. package/scripts/flow-trace +204 -0
  173. package/scripts/flow-transcript-chunking.js +1106 -0
  174. package/scripts/flow-transcript-digest.js +7918 -0
  175. package/scripts/flow-transcript-language.js +465 -0
  176. package/scripts/flow-transcript-parsing.js +1085 -0
  177. package/scripts/flow-transcript-stories.js +2194 -0
  178. package/scripts/flow-update-map +224 -0
  179. package/scripts/flow-utils.js +2242 -0
  180. package/scripts/flow-verification.js +644 -0
  181. package/scripts/flow-verify.js +1177 -0
  182. package/scripts/flow-voice-input.js +638 -0
  183. package/scripts/flow-watch +168 -0
  184. package/scripts/flow-workflow-steps.js +521 -0
  185. package/scripts/flow-workflow.js +1029 -0
  186. package/scripts/flow-worktree.js +489 -0
  187. package/scripts/hooks/adapters/base-adapter.js +102 -0
  188. package/scripts/hooks/adapters/claude-code.js +359 -0
  189. package/scripts/hooks/adapters/index.js +79 -0
  190. package/scripts/hooks/core/component-check.js +341 -0
  191. package/scripts/hooks/core/index.js +35 -0
  192. package/scripts/hooks/core/loop-check.js +241 -0
  193. package/scripts/hooks/core/session-context.js +294 -0
  194. package/scripts/hooks/core/task-gate.js +177 -0
  195. package/scripts/hooks/core/validation.js +230 -0
  196. package/scripts/hooks/entry/claude-code/post-tool-use.js +65 -0
  197. package/scripts/hooks/entry/claude-code/pre-tool-use.js +89 -0
  198. package/scripts/hooks/entry/claude-code/session-end.js +87 -0
  199. package/scripts/hooks/entry/claude-code/session-start.js +46 -0
  200. package/scripts/hooks/entry/claude-code/stop.js +43 -0
  201. package/scripts/postinstall.js +139 -0
  202. package/templates/browser-test-flow.json +56 -0
  203. package/templates/bug-report.md +43 -0
  204. package/templates/component-detail.md +42 -0
  205. package/templates/component.stories.tsx +49 -0
  206. package/templates/context/constraints.md +83 -0
  207. package/templates/context/conventions.md +177 -0
  208. package/templates/context/stack.md +60 -0
  209. package/templates/correction-report.md +90 -0
  210. package/templates/feature-proposal.md +35 -0
  211. package/templates/hybrid/_base.md +254 -0
  212. package/templates/hybrid/_patterns.md +45 -0
  213. package/templates/hybrid/create-component.md +127 -0
  214. package/templates/hybrid/create-file.md +56 -0
  215. package/templates/hybrid/create-hook.md +145 -0
  216. package/templates/hybrid/create-service.md +70 -0
  217. package/templates/hybrid/fix-bug.md +33 -0
  218. package/templates/hybrid/modify-file.md +55 -0
  219. package/templates/story.md +68 -0
  220. package/templates/task.json +56 -0
  221. package/templates/trace.md +69 -0
@@ -0,0 +1,123 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Wogi Flow - Output Utilities
5
+ *
6
+ * Terminal output formatting with colors and standard message types.
7
+ * Extracted from flow-utils.js for better modularity.
8
+ *
9
+ * Usage:
10
+ * const { colors, color, success, warn, error, info } = require('./flow-output');
11
+ */
12
+
13
+ // ============================================================
14
+ // Colors (ANSI escape codes)
15
+ // ============================================================
16
+
17
+ const colors = {
18
+ reset: '\x1b[0m',
19
+ bold: '\x1b[1m',
20
+ dim: '\x1b[2m',
21
+
22
+ red: '\x1b[31m',
23
+ green: '\x1b[32m',
24
+ yellow: '\x1b[33m',
25
+ blue: '\x1b[34m',
26
+ magenta: '\x1b[35m',
27
+ cyan: '\x1b[36m',
28
+ white: '\x1b[37m',
29
+
30
+ bgRed: '\x1b[41m',
31
+ bgGreen: '\x1b[42m',
32
+ bgYellow: '\x1b[43m',
33
+ bgBlue: '\x1b[44m',
34
+ };
35
+
36
+ /**
37
+ * Colorize text for terminal output
38
+ */
39
+ function color(colorName, text) {
40
+ if (process.env.DEBUG && !colors[colorName]) {
41
+ console.warn(`[DEBUG] Unknown color: "${colorName}"`);
42
+ }
43
+ return `${colors[colorName] || ''}${text}${colors.reset}`;
44
+ }
45
+
46
+ /**
47
+ * Print colored output
48
+ */
49
+ function print(colorName, text) {
50
+ console.log(color(colorName, text));
51
+ }
52
+
53
+ /**
54
+ * Print a styled header
55
+ */
56
+ function printHeader(title) {
57
+ console.log(color('cyan', '═'.repeat(50)));
58
+ console.log(color('cyan', ` ${title}`));
59
+ console.log(color('cyan', '═'.repeat(50)));
60
+ console.log('');
61
+ }
62
+
63
+ /**
64
+ * Print a section title
65
+ */
66
+ function printSection(title) {
67
+ console.log(color('cyan', title));
68
+ }
69
+
70
+ // ============================================================
71
+ // Standard Messaging Functions
72
+ // ============================================================
73
+ //
74
+ // STANDARD: All scripts should use these functions for consistent output:
75
+ // success(msg) - Green checkmark ✓ for successful operations
76
+ // warn(msg) - Yellow warning ⚠ for non-fatal issues
77
+ // error(msg) - Red X ✗ for errors (use before process.exit(1))
78
+ // info(msg) - Cyan info ℹ for informational messages
79
+ //
80
+ // Import with: const { success, warn, error, info } = require('./flow-output');
81
+ //
82
+ // AVOID: Direct console.log with color() for status messages.
83
+ // ============================================================
84
+
85
+ /**
86
+ * Print success message
87
+ */
88
+ function success(message) {
89
+ console.log(`${color('green', '✓')} ${message}`);
90
+ }
91
+
92
+ /**
93
+ * Print warning message
94
+ */
95
+ function warn(message) {
96
+ console.log(`${color('yellow', '⚠')} ${message}`);
97
+ }
98
+
99
+ /**
100
+ * Print error message
101
+ */
102
+ function error(message) {
103
+ console.log(`${color('red', '✗')} ${message}`);
104
+ }
105
+
106
+ /**
107
+ * Print info message
108
+ */
109
+ function info(message) {
110
+ console.log(`${color('cyan', 'ℹ')} ${message}`);
111
+ }
112
+
113
+ module.exports = {
114
+ colors,
115
+ color,
116
+ print,
117
+ printHeader,
118
+ printSection,
119
+ success,
120
+ warn,
121
+ error,
122
+ info,
123
+ };
@@ -0,0 +1,399 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Wogi Flow - Parallel Execution Detector
5
+ *
6
+ * Automatically detects when tasks can run in parallel and suggests/executes
7
+ * parallel execution based on configuration.
8
+ *
9
+ * Features:
10
+ * - Analyzes task dependencies and file overlaps
11
+ * - Suggests parallel execution when beneficial
12
+ * - Auto-executes parallel tasks when configured
13
+ * - Provides clear explanations of parallelization decisions
14
+ */
15
+
16
+ const fs = require('fs');
17
+ const path = require('path');
18
+ const { getConfig, getProjectRoot } = require('./flow-utils');
19
+ const {
20
+ detectDependencies,
21
+ findParallelizable,
22
+ canRunInParallel,
23
+ getParallelConfig
24
+ } = require('./flow-parallel');
25
+
26
+ /**
27
+ * Analyze tasks for parallel execution potential
28
+ */
29
+ function analyzeParallelPotential(tasks) {
30
+ if (!tasks || tasks.length < 2) {
31
+ return {
32
+ canParallelize: false,
33
+ reason: 'insufficient-tasks',
34
+ message: 'Need at least 2 tasks to parallelize'
35
+ };
36
+ }
37
+
38
+ const dependencies = detectDependencies(tasks);
39
+ const parallelizable = findParallelizable(tasks, new Set(), dependencies);
40
+ const config = getParallelConfig();
41
+
42
+ // Check minimum threshold
43
+ const minTasks = config.minTasksForParallel || 2;
44
+ if (parallelizable.length < minTasks) {
45
+ return {
46
+ canParallelize: false,
47
+ reason: 'below-threshold',
48
+ message: `Only ${parallelizable.length} tasks can run in parallel (minimum: ${minTasks})`,
49
+ parallelizable: parallelizable.map(t => t.id)
50
+ };
51
+ }
52
+
53
+ // Analyze file overlap for safety warnings
54
+ const fileOverlaps = analyzeFileOverlaps(tasks, dependencies);
55
+
56
+ // Calculate efficiency gain
57
+ const efficiencyGain = calculateEfficiencyGain(tasks, parallelizable);
58
+
59
+ return {
60
+ canParallelize: true,
61
+ parallelizable: parallelizable.map(t => ({
62
+ id: t.id,
63
+ title: t.title || t.description,
64
+ files: t.files || []
65
+ })),
66
+ totalTasks: tasks.length,
67
+ parallelCount: parallelizable.length,
68
+ dependencies,
69
+ fileOverlaps,
70
+ efficiencyGain,
71
+ waves: calculateWaves(tasks, dependencies),
72
+ recommendation: generateRecommendation(parallelizable, efficiencyGain, fileOverlaps)
73
+ };
74
+ }
75
+
76
+ /**
77
+ * Analyze file overlaps that might cause issues
78
+ */
79
+ function analyzeFileOverlaps(tasks, dependencies) {
80
+ const overlaps = [];
81
+ const fileToTasks = {};
82
+
83
+ for (const task of tasks) {
84
+ if (task.files && Array.isArray(task.files)) {
85
+ for (const file of task.files) {
86
+ if (!fileToTasks[file]) {
87
+ fileToTasks[file] = [];
88
+ }
89
+ fileToTasks[file].push(task.id);
90
+ }
91
+ }
92
+ }
93
+
94
+ for (const [file, taskIds] of Object.entries(fileToTasks)) {
95
+ if (taskIds.length > 1) {
96
+ overlaps.push({
97
+ file,
98
+ tasks: taskIds,
99
+ severity: taskIds.length > 2 ? 'high' : 'medium'
100
+ });
101
+ }
102
+ }
103
+
104
+ return overlaps;
105
+ }
106
+
107
+ /**
108
+ * Calculate efficiency gain from parallel execution
109
+ */
110
+ function calculateEfficiencyGain(tasks, parallelizable) {
111
+ // Simple estimation based on parallelizable ratio
112
+ const sequentialTime = tasks.length; // 1 unit per task
113
+ const parallelTime = Math.ceil(tasks.length / parallelizable.length);
114
+
115
+ return {
116
+ sequential: sequentialTime,
117
+ parallel: parallelTime,
118
+ savedTime: sequentialTime - parallelTime,
119
+ percentageGain: Math.round((1 - parallelTime / sequentialTime) * 100)
120
+ };
121
+ }
122
+
123
+ /**
124
+ * Calculate execution waves (groups that can run together)
125
+ */
126
+ function calculateWaves(tasks, dependencies) {
127
+ const waves = [];
128
+ const completed = new Set();
129
+
130
+ while (completed.size < tasks.length) {
131
+ const wave = [];
132
+
133
+ for (const task of tasks) {
134
+ if (completed.has(task.id)) continue;
135
+
136
+ const taskDeps = dependencies[task.id] || [];
137
+ const allDepsComplete = taskDeps.every(d => completed.has(d));
138
+
139
+ if (allDepsComplete) {
140
+ wave.push(task.id);
141
+ }
142
+ }
143
+
144
+ if (wave.length === 0) {
145
+ // Circular dependency or stuck
146
+ break;
147
+ }
148
+
149
+ waves.push(wave);
150
+ wave.forEach(id => completed.add(id));
151
+ }
152
+
153
+ return waves;
154
+ }
155
+
156
+ /**
157
+ * Generate a human-readable recommendation
158
+ */
159
+ function generateRecommendation(parallelizable, efficiencyGain, fileOverlaps) {
160
+ const lines = [];
161
+
162
+ if (parallelizable.length >= 3) {
163
+ lines.push('✅ RECOMMENDED: High parallelization potential');
164
+ } else if (parallelizable.length >= 2) {
165
+ lines.push('⚠️ POSSIBLE: Moderate parallelization potential');
166
+ }
167
+
168
+ lines.push(` ${parallelizable.length} tasks can run simultaneously`);
169
+ lines.push(` ~${efficiencyGain.percentageGain}% time savings expected`);
170
+
171
+ if (fileOverlaps.length > 0) {
172
+ const highSeverity = fileOverlaps.filter(o => o.severity === 'high');
173
+ if (highSeverity.length > 0) {
174
+ lines.push(` ⚠️ ${highSeverity.length} high-risk file overlaps detected`);
175
+ lines.push(` Consider enabling worktree isolation`);
176
+ }
177
+ }
178
+
179
+ return lines.join('\n');
180
+ }
181
+
182
+ /**
183
+ * Generate suggestion message for user
184
+ */
185
+ function generateSuggestionMessage(analysis) {
186
+ const lines = [
187
+ '',
188
+ '╔══════════════════════════════════════════════════════╗',
189
+ '║ 🔀 PARALLEL EXECUTION AVAILABLE ║',
190
+ '╠══════════════════════════════════════════════════════╣'
191
+ ];
192
+
193
+ lines.push(`║ ${analysis.parallelCount} of ${analysis.totalTasks} tasks can run in parallel`.padEnd(55) + '║');
194
+ lines.push(`║ Estimated time savings: ~${analysis.efficiencyGain.percentageGain}%`.padEnd(55) + '║');
195
+
196
+ lines.push('╠══════════════════════════════════════════════════════╣');
197
+ lines.push('║ Parallelizable tasks:'.padEnd(55) + '║');
198
+
199
+ for (const task of analysis.parallelizable.slice(0, 5)) {
200
+ const title = task.title || task.id;
201
+ const truncated = title.length > 45 ? title.substring(0, 42) + '...' : title;
202
+ lines.push(`║ • ${truncated}`.padEnd(55) + '║');
203
+ }
204
+
205
+ if (analysis.parallelizable.length > 5) {
206
+ lines.push(`║ ... and ${analysis.parallelizable.length - 5} more`.padEnd(55) + '║');
207
+ }
208
+
209
+ if (analysis.fileOverlaps.length > 0) {
210
+ lines.push('╠══════════════════════════════════════════════════════╣');
211
+ lines.push('║ ⚠️ File overlap warnings:'.padEnd(55) + '║');
212
+ for (const overlap of analysis.fileOverlaps.slice(0, 3)) {
213
+ const msg = `${overlap.file} → ${overlap.tasks.join(', ')}`;
214
+ const truncated = msg.length > 47 ? msg.substring(0, 44) + '...' : msg;
215
+ lines.push(`║ ${truncated}`.padEnd(55) + '║');
216
+ }
217
+ }
218
+
219
+ lines.push('╠══════════════════════════════════════════════════════╣');
220
+ lines.push('║ Options:'.padEnd(55) + '║');
221
+ lines.push('║ [P] Run in parallel'.padEnd(55) + '║');
222
+ lines.push('║ [S] Run sequentially'.padEnd(55) + '║');
223
+ lines.push('║ [W] Run parallel with worktree isolation'.padEnd(55) + '║');
224
+ lines.push('╚══════════════════════════════════════════════════════╝');
225
+
226
+ return lines.join('\n');
227
+ }
228
+
229
+ /**
230
+ * Check if parallel execution should be suggested
231
+ */
232
+ function shouldSuggestParallel(tasks) {
233
+ const config = getConfig();
234
+ const parallelConfig = config.parallel || {};
235
+
236
+ if (!parallelConfig.enabled) {
237
+ return { suggest: false, reason: 'parallel-disabled' };
238
+ }
239
+
240
+ if (!parallelConfig.autoDetect) {
241
+ return { suggest: false, reason: 'auto-detect-disabled' };
242
+ }
243
+
244
+ const analysis = analyzeParallelPotential(tasks);
245
+
246
+ if (!analysis.canParallelize) {
247
+ return { suggest: false, reason: analysis.reason };
248
+ }
249
+
250
+ if (parallelConfig.autoSuggest) {
251
+ return {
252
+ suggest: true,
253
+ analysis,
254
+ message: generateSuggestionMessage(analysis)
255
+ };
256
+ }
257
+
258
+ return { suggest: false, reason: 'auto-suggest-disabled' };
259
+ }
260
+
261
+ /**
262
+ * Check if parallel execution should auto-execute
263
+ * Uses autoExecute config option (not autoApprove which is for manual triggers)
264
+ */
265
+ function shouldAutoExecute(tasks) {
266
+ const config = getConfig();
267
+ const parallelConfig = config.parallel || {};
268
+
269
+ if (!parallelConfig.enabled) return false;
270
+ if (!parallelConfig.autoExecute) return false; // Use autoExecute, not autoApprove
271
+ if (!parallelConfig.autoDetect) return false;
272
+
273
+ const analysis = analyzeParallelPotential(tasks);
274
+ return analysis.canParallelize;
275
+ }
276
+
277
+ /**
278
+ * Load pending tasks from ready.json
279
+ */
280
+ function loadPendingTasks() {
281
+ const projectRoot = getProjectRoot();
282
+ const readyPath = path.join(projectRoot, '.workflow', 'state', 'ready.json');
283
+
284
+ if (!fs.existsSync(readyPath)) {
285
+ return [];
286
+ }
287
+
288
+ try {
289
+ const ready = JSON.parse(fs.readFileSync(readyPath, 'utf-8'));
290
+ return (ready.tasks || []).filter(t =>
291
+ t.status === 'pending' || t.status === 'ready'
292
+ );
293
+ } catch {
294
+ return [];
295
+ }
296
+ }
297
+
298
+ // ============================================================
299
+ // Exports
300
+ // ============================================================
301
+
302
+ module.exports = {
303
+ analyzeParallelPotential,
304
+ analyzeFileOverlaps,
305
+ calculateEfficiencyGain,
306
+ calculateWaves,
307
+ generateRecommendation,
308
+ generateSuggestionMessage,
309
+ shouldSuggestParallel,
310
+ shouldAutoExecute,
311
+ loadPendingTasks
312
+ };
313
+
314
+ // ============================================================
315
+ // CLI
316
+ // ============================================================
317
+
318
+ if (require.main === module) {
319
+ const args = process.argv.slice(2);
320
+ const command = args[0];
321
+
322
+ switch (command) {
323
+ case 'analyze': {
324
+ const tasks = loadPendingTasks();
325
+ if (tasks.length === 0) {
326
+ console.log('No pending tasks found in ready.json');
327
+ process.exit(0);
328
+ }
329
+
330
+ const analysis = analyzeParallelPotential(tasks);
331
+ console.log('\n📊 Parallel Execution Analysis\n');
332
+ console.log(`Total tasks: ${analysis.totalTasks || tasks.length}`);
333
+
334
+ if (analysis.canParallelize) {
335
+ console.log(`Can parallelize: ${analysis.parallelCount} tasks`);
336
+ console.log(`\nExecution waves:`);
337
+ analysis.waves.forEach((wave, i) => {
338
+ console.log(` Wave ${i + 1}: ${wave.join(', ')}`);
339
+ });
340
+ console.log(`\nEfficiency:`);
341
+ console.log(` Sequential time: ${analysis.efficiencyGain.sequential} units`);
342
+ console.log(` Parallel time: ${analysis.efficiencyGain.parallel} units`);
343
+ console.log(` Savings: ${analysis.efficiencyGain.percentageGain}%`);
344
+
345
+ if (analysis.fileOverlaps.length > 0) {
346
+ console.log(`\n⚠️ File overlaps:`);
347
+ analysis.fileOverlaps.forEach(o => {
348
+ console.log(` ${o.file}: ${o.tasks.join(', ')} (${o.severity})`);
349
+ });
350
+ }
351
+
352
+ console.log('\n' + analysis.recommendation);
353
+ } else {
354
+ console.log(`Cannot parallelize: ${analysis.reason}`);
355
+ console.log(analysis.message);
356
+ }
357
+ break;
358
+ }
359
+
360
+ case 'suggest': {
361
+ const tasks = loadPendingTasks();
362
+ const result = shouldSuggestParallel(tasks);
363
+
364
+ if (result.suggest) {
365
+ console.log(result.message);
366
+ } else {
367
+ console.log(`Parallel execution not suggested: ${result.reason}`);
368
+ }
369
+ break;
370
+ }
371
+
372
+ case 'config': {
373
+ const config = getParallelConfig();
374
+ console.log('\n⚙️ Parallel Execution Configuration\n');
375
+ console.log(JSON.stringify(config, null, 2));
376
+ break;
377
+ }
378
+
379
+ default:
380
+ console.log(`
381
+ Wogi Flow - Parallel Execution Detector
382
+
383
+ Usage:
384
+ node flow-parallel-detector.js <command>
385
+
386
+ Commands:
387
+ analyze Analyze pending tasks for parallel potential
388
+ suggest Check if parallel execution should be suggested
389
+ config Show parallel execution configuration
390
+
391
+ Configuration (config.json):
392
+ parallel.enabled: true Enable parallel execution
393
+ parallel.autoDetect: true Auto-detect parallel opportunities
394
+ parallel.autoSuggest: true Suggest parallel execution to user
395
+ parallel.autoApprove: false Auto-execute without approval
396
+ parallel.minTasksForParallel: 2 Minimum tasks to trigger
397
+ `);
398
+ }
399
+ }