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,396 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Wogi Flow - Regression Testing
5
+ *
6
+ * Tests random completed tasks to catch regressions early.
7
+ * Inspired by the "Long Running Agents" pattern where 3 random
8
+ * completed features are tested after each new task completion.
9
+ *
10
+ * Usage:
11
+ * flow regression # Test 3 random completed tasks
12
+ * flow regression --all # Test all completed tasks
13
+ * flow regression --task ID # Test specific task
14
+ * flow regression --count N # Test N random tasks
15
+ */
16
+
17
+ const fs = require('fs');
18
+ const path = require('path');
19
+ const { execSync } = require('child_process');
20
+ const { getProjectRoot, colors, getConfig } = require('./flow-utils');
21
+
22
+ const PROJECT_ROOT = getProjectRoot();
23
+ const STATE_DIR = path.join(PROJECT_ROOT, '.workflow', 'state');
24
+ const READY_PATH = path.join(STATE_DIR, 'ready.json');
25
+
26
+ function log(color, ...args) {
27
+ console.log(colors[color] + args.join(' ') + colors.reset);
28
+ }
29
+
30
+ /**
31
+ * Load ready.json and get completed tasks
32
+ */
33
+ function getCompletedTasks() {
34
+ if (!fs.existsSync(READY_PATH)) {
35
+ return [];
36
+ }
37
+
38
+ try {
39
+ const ready = JSON.parse(fs.readFileSync(READY_PATH, 'utf8'));
40
+ return ready.recentlyCompleted || [];
41
+ } catch (err) {
42
+ log('yellow', `Warning: Could not parse ready.json: ${err.message}`);
43
+ return [];
44
+ }
45
+ }
46
+
47
+ /**
48
+ * Find test files associated with a task
49
+ */
50
+ function findTestFiles(taskId, taskData) {
51
+ const testFiles = [];
52
+
53
+ // Check if task has explicit test files
54
+ if (taskData?.testFiles) {
55
+ testFiles.push(...taskData.testFiles);
56
+ return testFiles;
57
+ }
58
+
59
+ // Check if task has associated files
60
+ const files = taskData?.files || [];
61
+
62
+ for (const file of files) {
63
+ // Look for test files with common patterns
64
+ const ext = path.extname(file);
65
+ const base = file.slice(0, -ext.length);
66
+ const testPatterns = [
67
+ `${base}.test${ext}`,
68
+ `${base}.spec${ext}`,
69
+ file.replace(/src\//, 'src/__tests__/'),
70
+ file.replace(/src\/components\//, 'src/components/__tests__/'),
71
+ ];
72
+
73
+ for (const pattern of testPatterns) {
74
+ if (fs.existsSync(path.join(PROJECT_ROOT, pattern))) {
75
+ testFiles.push(pattern);
76
+ }
77
+ }
78
+ }
79
+
80
+ // Also look in request-log for files changed
81
+ const logPath = path.join(STATE_DIR, 'request-log.md');
82
+ if (fs.existsSync(logPath)) {
83
+ const logContent = fs.readFileSync(logPath, 'utf8');
84
+ // Escape special regex characters in taskId
85
+ const escapedTaskId = taskId.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
86
+ const taskPattern = new RegExp(`### R-\\d+.*${escapedTaskId}[\\s\\S]*?Files:\\s*([^\\n]+)`, 'i');
87
+ const match = logContent.match(taskPattern);
88
+ if (match) {
89
+ const mentionedFiles = match[1].split(',').map(f => f.trim());
90
+ for (const file of mentionedFiles) {
91
+ const cleanFile = file.replace(/`/g, '');
92
+ const ext = path.extname(cleanFile);
93
+ if (ext) {
94
+ const base = cleanFile.slice(0, -ext.length);
95
+ const testPatterns = [
96
+ `${base}.test${ext}`,
97
+ `${base}.spec${ext}`,
98
+ ];
99
+ for (const pattern of testPatterns) {
100
+ if (fs.existsSync(path.join(PROJECT_ROOT, pattern))) {
101
+ testFiles.push(pattern);
102
+ }
103
+ }
104
+ }
105
+ }
106
+ }
107
+ }
108
+
109
+ return [...new Set(testFiles)]; // Dedupe
110
+ }
111
+
112
+ /**
113
+ * Run tests for a specific task
114
+ */
115
+ function runTaskTests(taskId, taskData) {
116
+ const testFiles = findTestFiles(taskId, taskData);
117
+
118
+ if (testFiles.length === 0) {
119
+ return {
120
+ taskId,
121
+ skipped: true,
122
+ reason: 'No test files found'
123
+ };
124
+ }
125
+
126
+ log('white', ` Running tests: ${testFiles.join(', ')}`);
127
+
128
+ try {
129
+ // Try to run tests with common test runners
130
+ const testCommand = detectTestRunner(testFiles);
131
+ execSync(testCommand, {
132
+ cwd: PROJECT_ROOT,
133
+ stdio: 'pipe',
134
+ timeout: 60000 // 1 minute timeout per task
135
+ });
136
+
137
+ return {
138
+ taskId,
139
+ passed: true,
140
+ testFiles
141
+ };
142
+ } catch (err) {
143
+ return {
144
+ taskId,
145
+ passed: false,
146
+ error: err.message,
147
+ testFiles
148
+ };
149
+ }
150
+ }
151
+
152
+ /**
153
+ * Detect which test runner to use
154
+ */
155
+ function detectTestRunner(testFiles) {
156
+ const packageJson = path.join(PROJECT_ROOT, 'package.json');
157
+
158
+ if (fs.existsSync(packageJson)) {
159
+ try {
160
+ const pkg = JSON.parse(fs.readFileSync(packageJson, 'utf8'));
161
+
162
+ // Check scripts
163
+ if (pkg.scripts?.test) {
164
+ // If specific files, pass them
165
+ if (testFiles.length > 0) {
166
+ const fileArgs = testFiles.join(' ');
167
+ // Jest-style
168
+ if (pkg.devDependencies?.jest || pkg.dependencies?.jest) {
169
+ return `npx jest ${fileArgs} --passWithNoTests`;
170
+ }
171
+ // Vitest
172
+ if (pkg.devDependencies?.vitest || pkg.dependencies?.vitest) {
173
+ return `npx vitest run ${fileArgs}`;
174
+ }
175
+ // Mocha
176
+ if (pkg.devDependencies?.mocha || pkg.dependencies?.mocha) {
177
+ return `npx mocha ${fileArgs}`;
178
+ }
179
+ }
180
+ // Fallback to npm test
181
+ return 'npm test -- --passWithNoTests';
182
+ }
183
+ } catch (err) {
184
+ // package.json is malformed, fall through to default
185
+ }
186
+ }
187
+
188
+ // Default to jest
189
+ return `npx jest ${testFiles.join(' ')} --passWithNoTests`;
190
+ }
191
+
192
+ /**
193
+ * Pick random tasks from array using Fisher-Yates shuffle
194
+ */
195
+ function pickRandom(arr, count) {
196
+ const shuffled = [...arr];
197
+ // Fisher-Yates shuffle (unbiased)
198
+ for (let i = shuffled.length - 1; i > 0; i--) {
199
+ const j = Math.floor(Math.random() * (i + 1));
200
+ [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
201
+ }
202
+ return shuffled.slice(0, Math.min(count, arr.length));
203
+ }
204
+
205
+ /**
206
+ * Main regression testing function
207
+ */
208
+ async function runRegressionTests(options = {}) {
209
+ const config = getConfig();
210
+ const regressionConfig = config.regressionTesting || {};
211
+
212
+ // Check if enabled
213
+ if (!regressionConfig.enabled && !options.force) {
214
+ log('yellow', 'Regression testing is disabled. Enable in config.json or use --force');
215
+ return { skipped: true };
216
+ }
217
+
218
+ const sampleSize = options.count || regressionConfig.sampleSize || 3;
219
+ const onFailure = options.onFailure || regressionConfig.onFailure || 'warn';
220
+
221
+ // Get completed tasks
222
+ const completed = getCompletedTasks();
223
+
224
+ if (completed.length === 0) {
225
+ log('yellow', 'No completed tasks to test');
226
+ return { skipped: true, reason: 'No completed tasks' };
227
+ }
228
+
229
+ log('cyan', '\n=== Regression Testing ===\n');
230
+
231
+ // Determine which tasks to test
232
+ let tasksToTest;
233
+
234
+ if (options.all) {
235
+ tasksToTest = completed;
236
+ log('white', `Testing all ${completed.length} completed tasks...`);
237
+ } else if (options.taskId) {
238
+ const task = completed.find(t => t.id === options.taskId);
239
+ if (!task) {
240
+ log('red', `Task ${options.taskId} not found in completed tasks`);
241
+ return { failed: true, reason: 'Task not found' };
242
+ }
243
+ tasksToTest = [task];
244
+ log('white', `Testing specific task: ${options.taskId}`);
245
+ } else {
246
+ tasksToTest = pickRandom(completed, sampleSize);
247
+ log('white', `Testing ${tasksToTest.length} random tasks (of ${completed.length} completed)...`);
248
+ }
249
+
250
+ // Run tests
251
+ const results = [];
252
+
253
+ for (const task of tasksToTest) {
254
+ log('white', `\nšŸ“‹ Testing ${task.id}: ${task.title || task.name || 'Untitled'}`);
255
+
256
+ const result = runTaskTests(task.id, task);
257
+ results.push(result);
258
+
259
+ if (result.skipped) {
260
+ log('yellow', ` ā­ļø Skipped: ${result.reason}`);
261
+ } else if (result.passed) {
262
+ log('green', ` āœ… Passed`);
263
+ } else {
264
+ log('red', ` āŒ Failed: ${result.error?.substring(0, 100)}...`);
265
+ }
266
+ }
267
+
268
+ // Summary
269
+ const passed = results.filter(r => r.passed).length;
270
+ const failed = results.filter(r => r.passed === false).length;
271
+ const skipped = results.filter(r => r.skipped).length;
272
+
273
+ console.log('\n' + '─'.repeat(50));
274
+ log('white', '\nšŸ“Š Regression Test Summary');
275
+ log('green', ` āœ… Passed: ${passed}`);
276
+ log('red', ` āŒ Failed: ${failed}`);
277
+ log('yellow', ` ā­ļø Skipped: ${skipped}`);
278
+ console.log('');
279
+
280
+ // Handle failures
281
+ if (failed > 0) {
282
+ const failedTasks = results.filter(r => r.passed === false);
283
+
284
+ log('red', 'āš ļø Regression detected in:');
285
+ for (const f of failedTasks) {
286
+ log('red', ` - ${f.taskId}`);
287
+ }
288
+ console.log('');
289
+
290
+ if (onFailure === 'block') {
291
+ log('red', 'Blocking task completion due to regression failures');
292
+ process.exit(1);
293
+ } else if (onFailure === 'fix') {
294
+ log('yellow', 'Regressions need to be fixed before continuing');
295
+ // In the future, could integrate with auto-fix
296
+ }
297
+
298
+ return {
299
+ success: false,
300
+ tested: tasksToTest.length,
301
+ passed,
302
+ failed,
303
+ skipped,
304
+ failures: failedTasks
305
+ };
306
+ }
307
+
308
+ log('green', 'āœ… No regressions detected');
309
+
310
+ return {
311
+ success: true,
312
+ tested: tasksToTest.length,
313
+ passed,
314
+ failed,
315
+ skipped
316
+ };
317
+ }
318
+
319
+ // CLI handling
320
+ if (require.main === module) {
321
+ const args = process.argv.slice(2);
322
+
323
+ const options = {
324
+ all: args.includes('--all'),
325
+ force: args.includes('--force'),
326
+ taskId: null,
327
+ count: null,
328
+ onFailure: null
329
+ };
330
+
331
+ // Parse --task
332
+ const taskIdx = args.indexOf('--task');
333
+ if (taskIdx !== -1 && args[taskIdx + 1]) {
334
+ options.taskId = args[taskIdx + 1];
335
+ }
336
+
337
+ // Parse --count
338
+ const countIdx = args.indexOf('--count');
339
+ if (countIdx !== -1 && args[countIdx + 1]) {
340
+ options.count = parseInt(args[countIdx + 1], 10);
341
+ }
342
+
343
+ // Parse --on-failure
344
+ const failIdx = args.indexOf('--on-failure');
345
+ if (failIdx !== -1 && args[failIdx + 1]) {
346
+ options.onFailure = args[failIdx + 1];
347
+ }
348
+
349
+ // Help
350
+ if (args.includes('--help') || args.includes('-h')) {
351
+ console.log(`
352
+ Wogi Flow - Regression Testing
353
+
354
+ Usage:
355
+ flow regression Test 3 random completed tasks (default)
356
+ flow regression --all Test all completed tasks
357
+ flow regression --task ID Test specific task
358
+ flow regression --count N Test N random tasks
359
+ flow regression --force Run even if disabled in config
360
+ flow regression --on-failure warn|block|fix Override failure behavior
361
+
362
+ Configuration (config.json):
363
+ "regressionTesting": {
364
+ "enabled": true,
365
+ "sampleSize": 3,
366
+ "runOnTaskComplete": true,
367
+ "onFailure": "warn"
368
+ }
369
+
370
+ Exit codes:
371
+ 0 - All tests passed or skipped
372
+ 1 - Tests failed and onFailure is "block"
373
+ `);
374
+ process.exit(0);
375
+ }
376
+
377
+ const onFailure = options.onFailure || getConfig().regressionTesting?.onFailure || 'warn';
378
+
379
+ runRegressionTests(options)
380
+ .then(result => {
381
+ if (!result.success && onFailure === 'block') {
382
+ process.exit(1);
383
+ }
384
+ })
385
+ .catch(err => {
386
+ log('red', `Error: ${err.message}`);
387
+ process.exit(1);
388
+ });
389
+ }
390
+
391
+ // Export for use by other modules
392
+ module.exports = {
393
+ runRegressionTests,
394
+ getCompletedTasks,
395
+ findTestFiles
396
+ };