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,660 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Wogi Flow - Multi-Approach Validation
5
+ *
6
+ * Uses multi-trajectory validation approach:
7
+ * For complex tasks, generate multiple solution approaches,
8
+ * validate each, and select the best one.
9
+ *
10
+ * Modes:
11
+ * - "suggest" (default): Ask user before using extra tokens
12
+ * - "auto": Automatically use for high-complexity tasks
13
+ * - "off": Disabled
14
+ *
15
+ * This works in both normal and hybrid modes:
16
+ * - Normal: Claude generates N approaches, picks best after analysis
17
+ * - Hybrid: Generate N plans, execute best one with local LLM
18
+ *
19
+ * Usage as module:
20
+ * const { shouldUseMultiApproach, runMultiApproach } = require('./flow-multi-approach');
21
+ * if (shouldUseMultiApproach(complexity)) { ... }
22
+ *
23
+ * Usage as CLI:
24
+ * flow multi-approach "task description"
25
+ * flow multi-approach --analyze "task" # Just analyze, don't execute
26
+ */
27
+
28
+ const fs = require('fs');
29
+ const path = require('path');
30
+ const { getProjectRoot, getConfig, PATHS, colors, writeJson, ensureDir } = require('./flow-utils');
31
+
32
+ const PROJECT_ROOT = getProjectRoot();
33
+ const APPROACHES_DIR = path.join(PROJECT_ROOT, '.workflow', 'state', 'approaches');
34
+
35
+ // ============================================================
36
+ // Configuration
37
+ // ============================================================
38
+
39
+ /**
40
+ * Default configuration for multi-approach
41
+ */
42
+ const DEFAULT_CONFIG = {
43
+ enabled: true,
44
+ mode: 'suggest', // 'suggest', 'auto', 'off'
45
+ triggerOn: ['large', 'xl'], // Complexity levels that trigger
46
+ maxApproaches: 3, // Number of approaches to generate
47
+ validationGates: ['typecheck', 'lint'], // Gates to run on each approach
48
+ selectionStrategy: 'first-passing' // 'first-passing', 'best-score', 'user-choice'
49
+ };
50
+
51
+ /**
52
+ * Get multi-approach config from project config
53
+ */
54
+ function getMultiApproachConfig() {
55
+ const config = getConfig();
56
+ return {
57
+ ...DEFAULT_CONFIG,
58
+ ...(config.multiApproach || {})
59
+ };
60
+ }
61
+
62
+ // ============================================================
63
+ // Complexity Integration
64
+ // ============================================================
65
+
66
+ /**
67
+ * Check if multi-approach should be used for a given complexity
68
+ * @param {string|object} complexity - Complexity level string or complexity result object
69
+ * @returns {object} { shouldUse: boolean, reason: string, mode: string }
70
+ */
71
+ function shouldUseMultiApproach(complexity) {
72
+ const config = getMultiApproachConfig();
73
+
74
+ // Check if enabled
75
+ if (!config.enabled || config.mode === 'off') {
76
+ return {
77
+ shouldUse: false,
78
+ reason: 'Multi-approach is disabled',
79
+ mode: 'off'
80
+ };
81
+ }
82
+
83
+ // Extract complexity level
84
+ const level = typeof complexity === 'string'
85
+ ? complexity.toLowerCase()
86
+ : (complexity?.level || complexity?.complexity || 'medium').toLowerCase();
87
+
88
+ // Check if complexity triggers multi-approach
89
+ const triggers = config.triggerOn.map(t => t.toLowerCase());
90
+ const shouldTrigger = triggers.includes(level);
91
+
92
+ if (!shouldTrigger) {
93
+ return {
94
+ shouldUse: false,
95
+ reason: `Complexity "${level}" does not trigger multi-approach (triggers: ${triggers.join(', ')})`,
96
+ mode: config.mode
97
+ };
98
+ }
99
+
100
+ return {
101
+ shouldUse: true,
102
+ reason: `Complexity "${level}" triggers multi-approach`,
103
+ mode: config.mode,
104
+ needsUserApproval: config.mode === 'suggest'
105
+ };
106
+ }
107
+
108
+ // ============================================================
109
+ // Approach Generation
110
+ // ============================================================
111
+
112
+ /**
113
+ * Approach template for generating diverse solutions
114
+ */
115
+ const APPROACH_STRATEGIES = [
116
+ {
117
+ name: 'Direct',
118
+ description: 'Most straightforward implementation',
119
+ guidance: 'Implement the most direct, minimal solution. Prefer built-in features and existing utilities. Avoid abstractions unless necessary.'
120
+ },
121
+ {
122
+ name: 'Robust',
123
+ description: 'Focus on error handling and edge cases',
124
+ guidance: 'Focus on comprehensive error handling, validation, and edge cases. Add defensive checks. Consider what could go wrong.'
125
+ },
126
+ {
127
+ name: 'Reusable',
128
+ description: 'Maximize code reuse and patterns',
129
+ guidance: 'Focus on reusability and patterns. Extract shared logic. Consider how this might be extended later. Follow DRY principles.'
130
+ },
131
+ {
132
+ name: 'Performance',
133
+ description: 'Optimize for speed and efficiency',
134
+ guidance: 'Focus on performance. Consider caching, lazy loading, memoization. Avoid unnecessary computations or re-renders.'
135
+ },
136
+ {
137
+ name: 'Simple',
138
+ description: 'Minimize complexity and lines of code',
139
+ guidance: 'Minimize lines of code and complexity. Use concise patterns. Prefer clarity over cleverness. KISS principle.'
140
+ }
141
+ ];
142
+
143
+ /**
144
+ * Generate approach prompts for a task
145
+ * @param {object} task - Task description and context
146
+ * @param {number} count - Number of approaches to generate
147
+ * @returns {array} Array of approach configurations
148
+ */
149
+ function generateApproachPrompts(task, count = 3) {
150
+ const strategies = APPROACH_STRATEGIES.slice(0, count);
151
+
152
+ return strategies.map((strategy, index) => ({
153
+ id: `approach-${index + 1}`,
154
+ name: strategy.name,
155
+ description: strategy.description,
156
+ prompt: buildApproachPrompt(task, strategy),
157
+ strategy
158
+ }));
159
+ }
160
+
161
+ /**
162
+ * Build a prompt for a specific approach strategy
163
+ */
164
+ function buildApproachPrompt(task, strategy) {
165
+ return `
166
+ ## Approach: ${strategy.name}
167
+
168
+ ${strategy.guidance}
169
+
170
+ ### Task
171
+ ${task.description || task}
172
+
173
+ ### Context
174
+ ${task.context || 'Use existing project patterns and conventions.'}
175
+
176
+ ### Requirements
177
+ - Follow the "${strategy.name}" approach strictly
178
+ - Generate complete, working code
179
+ - Include necessary imports
180
+ - Follow project conventions
181
+
182
+ ### Output Format
183
+ Provide the implementation with:
184
+ 1. File path
185
+ 2. Complete code
186
+ 3. Brief explanation of approach
187
+
188
+ `.trim();
189
+ }
190
+
191
+ // ============================================================
192
+ // Approach Execution & Validation
193
+ // ============================================================
194
+
195
+ /**
196
+ * Approach result structure
197
+ */
198
+ function createApproachResult(approach) {
199
+ return {
200
+ id: approach.id,
201
+ name: approach.name,
202
+ status: 'pending', // pending, generating, validating, passed, failed
203
+ code: null,
204
+ files: [],
205
+ validationResults: {},
206
+ score: 0,
207
+ errors: [],
208
+ startTime: null,
209
+ endTime: null
210
+ };
211
+ }
212
+
213
+ /**
214
+ * Calculate score for an approach based on validation results
215
+ */
216
+ function calculateApproachScore(result) {
217
+ let score = 0;
218
+
219
+ // Base score for completion
220
+ if (result.code) score += 10;
221
+
222
+ // Validation gates
223
+ for (const [gate, passed] of Object.entries(result.validationResults)) {
224
+ if (passed) score += 20;
225
+ else score -= 10;
226
+ }
227
+
228
+ // Penalties
229
+ score -= result.errors.length * 5;
230
+
231
+ // Bonus for simplicity (fewer lines = higher score)
232
+ if (result.code) {
233
+ const lines = result.code.split('\n').length;
234
+ if (lines < 50) score += 10;
235
+ else if (lines < 100) score += 5;
236
+ else if (lines > 200) score -= 5;
237
+ }
238
+
239
+ return Math.max(0, score);
240
+ }
241
+
242
+ /**
243
+ * Select best approach from results
244
+ * @param {array} results - Array of approach results
245
+ * @param {string} strategy - Selection strategy
246
+ * @returns {object} Selected approach result
247
+ */
248
+ function selectBestApproach(results, strategy = 'first-passing') {
249
+ const validResults = results.filter(r => r.status !== 'failed');
250
+
251
+ if (validResults.length === 0) {
252
+ return {
253
+ selected: null,
254
+ reason: 'No approaches passed validation'
255
+ };
256
+ }
257
+
258
+ switch (strategy) {
259
+ case 'first-passing':
260
+ // Return first approach that passed all gates
261
+ const passing = validResults.find(r => r.status === 'passed');
262
+ return {
263
+ selected: passing || validResults[0],
264
+ reason: passing
265
+ ? `Selected first passing approach: ${passing.name}`
266
+ : `No fully passing approach, selected best available: ${validResults[0].name}`
267
+ };
268
+
269
+ case 'best-score':
270
+ // Sort by score and return highest
271
+ validResults.sort((a, b) => b.score - a.score);
272
+ return {
273
+ selected: validResults[0],
274
+ reason: `Selected highest scoring approach: ${validResults[0].name} (score: ${validResults[0].score})`
275
+ };
276
+
277
+ case 'user-choice':
278
+ // Return all for user to choose
279
+ return {
280
+ selected: null,
281
+ candidates: validResults,
282
+ reason: 'Awaiting user selection'
283
+ };
284
+
285
+ default:
286
+ return {
287
+ selected: validResults[0],
288
+ reason: `Default selection: ${validResults[0].name}`
289
+ };
290
+ }
291
+ }
292
+
293
+ // ============================================================
294
+ // Multi-Approach Session Management
295
+ // ============================================================
296
+
297
+ /**
298
+ * Create a new multi-approach session
299
+ */
300
+ function createSession(task, approaches) {
301
+ const sessionId = `ma-${Date.now()}`;
302
+
303
+ return {
304
+ id: sessionId,
305
+ task: typeof task === 'string' ? { description: task } : task,
306
+ approaches: approaches.map(createApproachResult),
307
+ status: 'created', // created, generating, validating, selecting, complete, failed
308
+ selectedApproach: null,
309
+ createdAt: new Date().toISOString(),
310
+ updatedAt: new Date().toISOString()
311
+ };
312
+ }
313
+
314
+ /**
315
+ * Save session to disk
316
+ */
317
+ function saveSession(session) {
318
+ session.updatedAt = new Date().toISOString();
319
+
320
+ ensureDir(APPROACHES_DIR);
321
+
322
+ const sessionPath = path.join(APPROACHES_DIR, `${session.id}.json`);
323
+ // Use atomic writeJson to prevent data corruption
324
+ writeJson(sessionPath, session);
325
+
326
+ return sessionPath;
327
+ }
328
+
329
+ /**
330
+ * Load session from disk
331
+ */
332
+ function loadSession(sessionId) {
333
+ const sessionPath = path.join(APPROACHES_DIR, `${sessionId}.json`);
334
+
335
+ if (!fs.existsSync(sessionPath)) {
336
+ return null;
337
+ }
338
+
339
+ return JSON.parse(fs.readFileSync(sessionPath, 'utf-8'));
340
+ }
341
+
342
+ /**
343
+ * List recent sessions
344
+ */
345
+ function listSessions(limit = 10) {
346
+ if (!fs.existsSync(APPROACHES_DIR)) {
347
+ return [];
348
+ }
349
+
350
+ return fs.readdirSync(APPROACHES_DIR)
351
+ .filter(f => f.endsWith('.json'))
352
+ .map(f => {
353
+ const session = JSON.parse(
354
+ fs.readFileSync(path.join(APPROACHES_DIR, f), 'utf-8')
355
+ );
356
+ return {
357
+ id: session.id,
358
+ task: session.task?.description?.slice(0, 50) + '...',
359
+ status: session.status,
360
+ selectedApproach: session.selectedApproach?.name,
361
+ createdAt: session.createdAt
362
+ };
363
+ })
364
+ .sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt))
365
+ .slice(0, limit);
366
+ }
367
+
368
+ // ============================================================
369
+ // Main Entry Points
370
+ // ============================================================
371
+
372
+ /**
373
+ * Analyze a task for multi-approach suitability
374
+ * Does not execute, just returns analysis
375
+ */
376
+ function analyzeForMultiApproach(taskDescription, complexityLevel = null) {
377
+ // Try to assess complexity if not provided
378
+ let complexity = complexityLevel;
379
+ if (!complexity) {
380
+ try {
381
+ const { assessTaskComplexity } = require('./flow-complexity');
382
+ const result = assessTaskComplexity(taskDescription);
383
+ complexity = result.level;
384
+ } catch {
385
+ complexity = 'medium';
386
+ }
387
+ }
388
+
389
+ const shouldUse = shouldUseMultiApproach(complexity);
390
+ const config = getMultiApproachConfig();
391
+
392
+ // Generate approach previews
393
+ const approaches = generateApproachPrompts(taskDescription, config.maxApproaches);
394
+
395
+ return {
396
+ task: taskDescription,
397
+ complexity,
398
+ multiApproach: shouldUse,
399
+ config: {
400
+ mode: config.mode,
401
+ maxApproaches: config.maxApproaches,
402
+ triggerOn: config.triggerOn,
403
+ selectionStrategy: config.selectionStrategy
404
+ },
405
+ approaches: approaches.map(a => ({
406
+ id: a.id,
407
+ name: a.name,
408
+ description: a.description
409
+ }))
410
+ };
411
+ }
412
+
413
+ /**
414
+ * Start a multi-approach session for a task
415
+ * Returns session that can be executed step by step
416
+ */
417
+ function startMultiApproach(taskDescription, options = {}) {
418
+ const config = getMultiApproachConfig();
419
+
420
+ const approaches = generateApproachPrompts(
421
+ taskDescription,
422
+ options.maxApproaches || config.maxApproaches
423
+ );
424
+
425
+ const session = createSession(taskDescription, approaches);
426
+ session.status = 'created';
427
+ session.config = config;
428
+
429
+ // Save session
430
+ saveSession(session);
431
+
432
+ return session;
433
+ }
434
+
435
+ /**
436
+ * Format analysis for display
437
+ */
438
+ function formatAnalysis(analysis) {
439
+ let output = '';
440
+
441
+ output += `${colors.cyan}Multi-Approach Analysis${colors.reset}\n`;
442
+ output += `${'═'.repeat(50)}\n\n`;
443
+
444
+ // Task summary
445
+ output += `${colors.bold}Task:${colors.reset} ${analysis.task.slice(0, 100)}${analysis.task.length > 100 ? '...' : ''}\n`;
446
+ output += `${colors.bold}Complexity:${colors.reset} ${analysis.complexity}\n\n`;
447
+
448
+ // Multi-approach decision
449
+ if (analysis.multiApproach.shouldUse) {
450
+ output += `${colors.green}✓ Multi-approach recommended${colors.reset}\n`;
451
+ output += ` Reason: ${analysis.multiApproach.reason}\n`;
452
+
453
+ if (analysis.multiApproach.needsUserApproval) {
454
+ output += ` ${colors.yellow}Mode is "suggest" - will ask for approval${colors.reset}\n`;
455
+ }
456
+ } else {
457
+ output += `${colors.dim}○ Multi-approach not needed${colors.reset}\n`;
458
+ output += ` Reason: ${analysis.multiApproach.reason}\n`;
459
+ }
460
+
461
+ output += '\n';
462
+
463
+ // Approaches
464
+ if (analysis.approaches.length > 0) {
465
+ output += `${colors.bold}Available Approaches (${analysis.approaches.length}):${colors.reset}\n`;
466
+ for (const approach of analysis.approaches) {
467
+ output += ` ${colors.cyan}${approach.name}${colors.reset}: ${approach.description}\n`;
468
+ }
469
+ output += '\n';
470
+ }
471
+
472
+ // Config
473
+ output += `${colors.dim}Config: mode=${analysis.config.mode}, triggers=${analysis.config.triggerOn.join(',')}${colors.reset}\n`;
474
+
475
+ return output;
476
+ }
477
+
478
+ /**
479
+ * Format suggestion prompt for user
480
+ */
481
+ function formatSuggestionPrompt(analysis) {
482
+ return `
483
+ ${colors.yellow}Multi-Approach Suggestion${colors.reset}
484
+
485
+ This task has "${analysis.complexity}" complexity. Using multi-approach validation
486
+ could help find the best solution but will use more tokens.
487
+
488
+ ${colors.bold}What multi-approach does:${colors.reset}
489
+ 1. Generates ${analysis.config.maxApproaches} different solutions
490
+ 2. Validates each through quality gates
491
+ 3. Selects the best passing approach
492
+
493
+ ${colors.bold}Approaches that would be tried:${colors.reset}
494
+ ${analysis.approaches.map(a => ` • ${a.name}: ${a.description}`).join('\n')}
495
+
496
+ ${colors.bold}Options:${colors.reset}
497
+ [Y] Yes, use multi-approach (more thorough)
498
+ [N] No, use single approach (faster, less tokens)
499
+ [A] Always use for this complexity level
500
+ [S] Show me more details
501
+
502
+ `.trim();
503
+ }
504
+
505
+ // ============================================================
506
+ // CLI
507
+ // ============================================================
508
+
509
+ function showHelp() {
510
+ console.log(`
511
+ Wogi Flow - Multi-Approach Validation
512
+
513
+ Generate multiple solution approaches for complex tasks, validate each,
514
+ and select the best one.
515
+
516
+ Usage:
517
+ flow multi-approach "task description"
518
+ flow multi-approach --analyze "task" # Analyze without executing
519
+ flow multi-approach --list # List recent sessions
520
+ flow multi-approach --config # Show configuration
521
+
522
+ Options:
523
+ --analyze Just analyze, don't start session
524
+ --list List recent multi-approach sessions
525
+ --config Show current configuration
526
+ --json Output as JSON
527
+ --help, -h Show this help
528
+
529
+ Modes (configurable in config.json):
530
+ "suggest" Ask user before using extra tokens (default)
531
+ "auto" Automatically use for high-complexity tasks
532
+ "off" Disabled
533
+
534
+ Examples:
535
+ flow multi-approach "Implement user authentication with OAuth"
536
+ flow multi-approach --analyze "Refactor the payment module"
537
+ `);
538
+ }
539
+
540
+ function main() {
541
+ const args = process.argv.slice(2);
542
+
543
+ if (args.includes('--help') || args.includes('-h')) {
544
+ showHelp();
545
+ process.exit(0);
546
+ }
547
+
548
+ const jsonOutput = args.includes('--json');
549
+
550
+ if (args.includes('--list')) {
551
+ const sessions = listSessions();
552
+ if (jsonOutput) {
553
+ console.log(JSON.stringify(sessions, null, 2));
554
+ } else {
555
+ console.log(`${colors.cyan}Recent Multi-Approach Sessions${colors.reset}\n`);
556
+ if (sessions.length === 0) {
557
+ console.log(`${colors.dim}No sessions found.${colors.reset}`);
558
+ } else {
559
+ for (const s of sessions) {
560
+ const statusIcon = s.status === 'complete' ? colors.green + '✓' : colors.yellow + '○';
561
+ console.log(`${statusIcon} ${s.id}${colors.reset}`);
562
+ console.log(` Task: ${s.task}`);
563
+ console.log(` Status: ${s.status}`);
564
+ if (s.selectedApproach) {
565
+ console.log(` Selected: ${s.selectedApproach}`);
566
+ }
567
+ console.log('');
568
+ }
569
+ }
570
+ }
571
+ process.exit(0);
572
+ }
573
+
574
+ if (args.includes('--config')) {
575
+ const config = getMultiApproachConfig();
576
+ if (jsonOutput) {
577
+ console.log(JSON.stringify(config, null, 2));
578
+ } else {
579
+ console.log(`${colors.cyan}Multi-Approach Configuration${colors.reset}\n`);
580
+ console.log(` Enabled: ${config.enabled}`);
581
+ console.log(` Mode: ${config.mode}`);
582
+ console.log(` Trigger on: ${config.triggerOn.join(', ')}`);
583
+ console.log(` Max approaches: ${config.maxApproaches}`);
584
+ console.log(` Selection: ${config.selectionStrategy}`);
585
+ }
586
+ process.exit(0);
587
+ }
588
+
589
+ // Get task description
590
+ const taskDescription = args
591
+ .filter(a => !a.startsWith('--'))
592
+ .join(' ');
593
+
594
+ if (!taskDescription) {
595
+ console.log(`${colors.red}Error: Please provide a task description${colors.reset}`);
596
+ showHelp();
597
+ process.exit(1);
598
+ }
599
+
600
+ // Analyze or start session
601
+ if (args.includes('--analyze')) {
602
+ const analysis = analyzeForMultiApproach(taskDescription);
603
+
604
+ if (jsonOutput) {
605
+ console.log(JSON.stringify(analysis, null, 2));
606
+ } else {
607
+ console.log(formatAnalysis(analysis));
608
+ }
609
+ } else {
610
+ // Start a session
611
+ const session = startMultiApproach(taskDescription);
612
+
613
+ if (jsonOutput) {
614
+ console.log(JSON.stringify(session, null, 2));
615
+ } else {
616
+ console.log(`${colors.green}✓${colors.reset} Created multi-approach session: ${session.id}`);
617
+ console.log(` Status: ${session.status}`);
618
+ console.log(` Approaches: ${session.approaches.length}`);
619
+ console.log(`\n Session saved to: ${APPROACHES_DIR}/${session.id}.json`);
620
+ console.log(`\n${colors.dim}Note: This creates a session. Execution is handled by the orchestrator.${colors.reset}`);
621
+ }
622
+ }
623
+ }
624
+
625
+ // ============================================================
626
+ // Exports
627
+ // ============================================================
628
+
629
+ module.exports = {
630
+ // Configuration
631
+ getMultiApproachConfig,
632
+ DEFAULT_CONFIG,
633
+
634
+ // Decision making
635
+ shouldUseMultiApproach,
636
+ analyzeForMultiApproach,
637
+
638
+ // Approach generation
639
+ generateApproachPrompts,
640
+ APPROACH_STRATEGIES,
641
+
642
+ // Session management
643
+ createSession,
644
+ startMultiApproach,
645
+ saveSession,
646
+ loadSession,
647
+ listSessions,
648
+
649
+ // Validation & selection
650
+ calculateApproachScore,
651
+ selectBestApproach,
652
+
653
+ // Formatting
654
+ formatAnalysis,
655
+ formatSuggestionPrompt
656
+ };
657
+
658
+ if (require.main === module) {
659
+ main();
660
+ }