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,644 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Wogi Flow - File-Based Verification (Priority 4)
5
+ *
6
+ * Every phase produces artifacts. Never trust chat output.
7
+ * Explicit success criteria with commands and pass/fail conditions.
8
+ *
9
+ * Uses file-based validation approach.
10
+ *
11
+ * Key principle: "Logs are state - next iteration depends on them"
12
+ *
13
+ * Usage:
14
+ * const { runVerification, saveVerificationResult } = require('./flow-verification');
15
+ * const result = await runVerification(taskId, 'implementation');
16
+ */
17
+
18
+ const fs = require('fs');
19
+ const path = require('path');
20
+ const { execSync, spawn } = require('child_process');
21
+ const { getProjectRoot, getConfig, PATHS, colors } = require('./flow-utils');
22
+
23
+ const PROJECT_ROOT = getProjectRoot();
24
+ const VERIFICATIONS_DIR = path.join(PROJECT_ROOT, '.workflow', 'verifications');
25
+
26
+ // ============================================================
27
+ // Verification Execution
28
+ // ============================================================
29
+
30
+ /**
31
+ * Run verification commands for a task phase
32
+ *
33
+ * @param {string} taskId - Task ID
34
+ * @param {string} phase - Phase name (spec, test, implementation, final)
35
+ * @param {object} options - Verification options
36
+ * @param {Array} options.commands - Commands to run (overrides defaults)
37
+ * @param {boolean} options.failFast - Stop on first failure
38
+ * @param {number} options.timeout - Command timeout in ms
39
+ */
40
+ async function runVerification(taskId, phase, options = {}) {
41
+ const config = getConfig();
42
+ const commands = options.commands || getDefaultCommands(phase, config);
43
+ const failFast = options.failFast !== false;
44
+ const timeout = options.timeout || 120000;
45
+
46
+ const result = {
47
+ taskId,
48
+ phase,
49
+ timestamp: new Date().toISOString(),
50
+ results: [],
51
+ allPassed: true,
52
+ duration: 0
53
+ };
54
+
55
+ const startTime = Date.now();
56
+
57
+ for (const cmd of commands) {
58
+ const cmdResult = await runCommand(cmd, timeout);
59
+ result.results.push(cmdResult);
60
+
61
+ if (!cmdResult.passed) {
62
+ result.allPassed = false;
63
+ if (failFast) {
64
+ break;
65
+ }
66
+ }
67
+ }
68
+
69
+ result.duration = Date.now() - startTime;
70
+
71
+ // Save verification result to file
72
+ saveVerificationResult(taskId, phase, result);
73
+
74
+ return result;
75
+ }
76
+
77
+ /**
78
+ * Run a single command and capture result
79
+ */
80
+ async function runCommand(cmd, timeout) {
81
+ const result = {
82
+ command: cmd.command,
83
+ description: cmd.description || cmd.command,
84
+ required: cmd.required !== false,
85
+ expectedExitCode: cmd.expectedExitCode || 0,
86
+ startTime: new Date().toISOString(),
87
+ passed: false,
88
+ exitCode: null,
89
+ stdout: '',
90
+ stderr: '',
91
+ duration: 0,
92
+ error: null
93
+ };
94
+
95
+ const startTime = Date.now();
96
+
97
+ try {
98
+ const output = execSync(cmd.command, {
99
+ cwd: PROJECT_ROOT,
100
+ encoding: 'utf-8',
101
+ timeout,
102
+ stdio: 'pipe',
103
+ maxBuffer: 10 * 1024 * 1024 // 10MB
104
+ });
105
+
106
+ result.stdout = output;
107
+ result.exitCode = 0;
108
+ result.passed = result.exitCode === result.expectedExitCode;
109
+ } catch (err) {
110
+ result.exitCode = err.status || 1;
111
+ result.stdout = err.stdout || '';
112
+ result.stderr = err.stderr || '';
113
+ result.error = err.message;
114
+ result.passed = result.exitCode === result.expectedExitCode;
115
+ }
116
+
117
+ result.duration = Date.now() - startTime;
118
+ result.endTime = new Date().toISOString();
119
+
120
+ return result;
121
+ }
122
+
123
+ /**
124
+ * Get default verification commands for a phase
125
+ */
126
+ function getDefaultCommands(phase, config) {
127
+ const commands = [];
128
+
129
+ switch (phase) {
130
+ case 'spec':
131
+ // Spec phase - just validate spec exists
132
+ commands.push({
133
+ command: 'echo "Spec validation"',
134
+ description: 'Validate spec exists',
135
+ required: true
136
+ });
137
+ break;
138
+
139
+ case 'test':
140
+ // Test-first phase - run tests (expecting some to fail initially)
141
+ commands.push({
142
+ command: 'npm test -- --passWithNoTests 2>/dev/null || true',
143
+ description: 'Run tests (initial)',
144
+ required: false
145
+ });
146
+ break;
147
+
148
+ case 'implementation':
149
+ // After implementation - lint and typecheck
150
+ commands.push({
151
+ command: 'npm run lint 2>/dev/null || npx eslint . --ext .ts,.tsx,.js,.jsx --max-warnings 0 2>/dev/null || echo "lint skipped"',
152
+ description: 'Run linter',
153
+ required: false
154
+ });
155
+ commands.push({
156
+ command: 'npm run typecheck 2>/dev/null || npx tsc --noEmit 2>/dev/null || echo "typecheck skipped"',
157
+ description: 'Run type checker',
158
+ required: false
159
+ });
160
+ break;
161
+
162
+ case 'final':
163
+ // Final verification - all gates must pass
164
+ if (config.validation?.beforeCommit?.commands) {
165
+ for (const cmd of config.validation.beforeCommit.commands) {
166
+ commands.push({
167
+ command: cmd,
168
+ description: cmd,
169
+ required: true
170
+ });
171
+ }
172
+ } else {
173
+ commands.push({
174
+ command: 'npm run lint 2>/dev/null || echo "lint not configured"',
175
+ description: 'Run linter',
176
+ required: false
177
+ });
178
+ commands.push({
179
+ command: 'npm run typecheck 2>/dev/null || echo "typecheck not configured"',
180
+ description: 'Run type checker',
181
+ required: false
182
+ });
183
+ commands.push({
184
+ command: 'npm test 2>/dev/null || echo "tests not configured"',
185
+ description: 'Run tests',
186
+ required: false
187
+ });
188
+ }
189
+ break;
190
+
191
+ default:
192
+ // Generic verification
193
+ commands.push({
194
+ command: 'npm run lint 2>/dev/null || echo "lint not configured"',
195
+ description: 'Run linter',
196
+ required: false
197
+ });
198
+ }
199
+
200
+ return commands;
201
+ }
202
+
203
+ // ============================================================
204
+ // Verification Artifacts
205
+ // ============================================================
206
+
207
+ /**
208
+ * Save verification result to file
209
+ */
210
+ function saveVerificationResult(taskId, phase, result) {
211
+ // Ensure directory exists
212
+ if (!fs.existsSync(VERIFICATIONS_DIR)) {
213
+ fs.mkdirSync(VERIFICATIONS_DIR, { recursive: true });
214
+ }
215
+
216
+ // Save JSON result
217
+ const filename = `${taskId}-${phase}.json`;
218
+ const filePath = path.join(VERIFICATIONS_DIR, filename);
219
+ fs.writeFileSync(filePath, JSON.stringify(result, null, 2), 'utf-8');
220
+
221
+ // Also append to verification log
222
+ appendToVerificationLog(taskId, phase, result);
223
+
224
+ return filePath;
225
+ }
226
+
227
+ /**
228
+ * Load verification result for a task/phase
229
+ */
230
+ function loadVerificationResult(taskId, phase) {
231
+ const filename = `${taskId}-${phase}.json`;
232
+ const filePath = path.join(VERIFICATIONS_DIR, filename);
233
+
234
+ if (!fs.existsSync(filePath)) {
235
+ return null;
236
+ }
237
+
238
+ try {
239
+ return JSON.parse(fs.readFileSync(filePath, 'utf-8'));
240
+ } catch {
241
+ return null;
242
+ }
243
+ }
244
+
245
+ /**
246
+ * Get all verification results for a task
247
+ */
248
+ function getAllVerificationResults(taskId) {
249
+ if (!fs.existsSync(VERIFICATIONS_DIR)) {
250
+ return [];
251
+ }
252
+
253
+ const files = fs.readdirSync(VERIFICATIONS_DIR)
254
+ .filter(f => f.startsWith(`${taskId}-`) && f.endsWith('.json'));
255
+
256
+ return files.map(f => {
257
+ try {
258
+ return JSON.parse(fs.readFileSync(path.join(VERIFICATIONS_DIR, f), 'utf-8'));
259
+ } catch {
260
+ return null;
261
+ }
262
+ }).filter(Boolean);
263
+ }
264
+
265
+ /**
266
+ * Append to verification log (human-readable)
267
+ */
268
+ function appendToVerificationLog(taskId, phase, result) {
269
+ const logPath = path.join(VERIFICATIONS_DIR, 'verification-log.md');
270
+
271
+ let content = '';
272
+ if (fs.existsSync(logPath)) {
273
+ content = fs.readFileSync(logPath, 'utf-8');
274
+ } else {
275
+ content = '# Verification Log\n\nFile-based verification results.\n\n';
276
+ }
277
+
278
+ const status = result.allPassed ? '✓ PASSED' : '✗ FAILED';
279
+ const entry = `
280
+ ## ${taskId} - ${phase} [${status}]
281
+ **Time:** ${result.timestamp}
282
+ **Duration:** ${result.duration}ms
283
+
284
+ | Command | Status | Exit | Duration |
285
+ |---------|--------|------|----------|
286
+ ${result.results.map(r =>
287
+ `| \`${r.command.slice(0, 40)}${r.command.length > 40 ? '...' : ''}\` | ${r.passed ? '✓' : '✗'} | ${r.exitCode} | ${r.duration}ms |`
288
+ ).join('\n')}
289
+
290
+ ---
291
+ `;
292
+
293
+ content += entry;
294
+ fs.writeFileSync(logPath, content, 'utf-8');
295
+ }
296
+
297
+ // ============================================================
298
+ // Structured Execution Loop (Priority 3)
299
+ // ============================================================
300
+
301
+ /**
302
+ * Execute structured loop: Spec → Test → Implement → Verify
303
+ * This is the core structured execution model
304
+ *
305
+ * @param {string} taskId - Task ID
306
+ * @param {object} callbacks - Phase callbacks
307
+ */
308
+ async function executeStructuredLoop(taskId, callbacks = {}) {
309
+ const phases = ['spec', 'test', 'implementation', 'final'];
310
+ const loopState = {
311
+ taskId,
312
+ startTime: new Date().toISOString(),
313
+ phases: {},
314
+ currentPhase: null,
315
+ completed: false,
316
+ success: false
317
+ };
318
+
319
+ for (const phase of phases) {
320
+ loopState.currentPhase = phase;
321
+ loopState.phases[phase] = {
322
+ startTime: new Date().toISOString(),
323
+ status: 'running'
324
+ };
325
+
326
+ // Call phase callback if provided
327
+ if (callbacks[phase]) {
328
+ try {
329
+ await callbacks[phase](loopState);
330
+ } catch (err) {
331
+ loopState.phases[phase].status = 'failed';
332
+ loopState.phases[phase].error = err.message;
333
+ break;
334
+ }
335
+ }
336
+
337
+ // Run verification for this phase
338
+ const verification = await runVerification(taskId, phase);
339
+
340
+ loopState.phases[phase].verification = {
341
+ passed: verification.allPassed,
342
+ duration: verification.duration,
343
+ failedCommands: verification.results
344
+ .filter(r => !r.passed)
345
+ .map(r => r.command)
346
+ };
347
+
348
+ if (!verification.allPassed && phase === 'final') {
349
+ loopState.phases[phase].status = 'failed';
350
+ break;
351
+ }
352
+
353
+ loopState.phases[phase].status = 'completed';
354
+ loopState.phases[phase].endTime = new Date().toISOString();
355
+ }
356
+
357
+ loopState.completed = true;
358
+ loopState.success = Object.values(loopState.phases)
359
+ .every(p => p.status === 'completed');
360
+ loopState.endTime = new Date().toISOString();
361
+
362
+ // Save loop state
363
+ saveLoopState(taskId, loopState);
364
+
365
+ return loopState;
366
+ }
367
+
368
+ /**
369
+ * Save loop state to file
370
+ */
371
+ function saveLoopState(taskId, state) {
372
+ const loopDir = path.join(VERIFICATIONS_DIR, 'loops');
373
+ if (!fs.existsSync(loopDir)) {
374
+ fs.mkdirSync(loopDir, { recursive: true });
375
+ }
376
+
377
+ const filePath = path.join(loopDir, `${taskId}-loop.json`);
378
+ fs.writeFileSync(filePath, JSON.stringify(state, null, 2), 'utf-8');
379
+
380
+ return filePath;
381
+ }
382
+
383
+ /**
384
+ * Load loop state
385
+ */
386
+ function loadLoopState(taskId) {
387
+ const filePath = path.join(VERIFICATIONS_DIR, 'loops', `${taskId}-loop.json`);
388
+
389
+ if (!fs.existsSync(filePath)) {
390
+ return null;
391
+ }
392
+
393
+ try {
394
+ return JSON.parse(fs.readFileSync(filePath, 'utf-8'));
395
+ } catch {
396
+ return null;
397
+ }
398
+ }
399
+
400
+ // ============================================================
401
+ // Self-Reflection Checkpoints (Priority 6)
402
+ // ============================================================
403
+
404
+ /**
405
+ * Create a reflection checkpoint
406
+ * Pauses execution and records reflection data
407
+ *
408
+ * @param {string} taskId - Task ID
409
+ * @param {string} checkpoint - Checkpoint name
410
+ * @param {object} context - Context for reflection
411
+ */
412
+ function createReflectionCheckpoint(taskId, checkpoint, context = {}) {
413
+ const reflectionsDir = path.join(VERIFICATIONS_DIR, 'reflections');
414
+ if (!fs.existsSync(reflectionsDir)) {
415
+ fs.mkdirSync(reflectionsDir, { recursive: true });
416
+ }
417
+
418
+ const reflection = {
419
+ taskId,
420
+ checkpoint,
421
+ timestamp: new Date().toISOString(),
422
+ context,
423
+ questions: getReflectionQuestions(checkpoint),
424
+ answers: {}
425
+ };
426
+
427
+ const filePath = path.join(reflectionsDir, `${taskId}-${checkpoint}.json`);
428
+ fs.writeFileSync(filePath, JSON.stringify(reflection, null, 2), 'utf-8');
429
+
430
+ return reflection;
431
+ }
432
+
433
+ /**
434
+ * Get reflection questions for a checkpoint
435
+ */
436
+ function getReflectionQuestions(checkpoint) {
437
+ const questions = {
438
+ 'post-spec': [
439
+ 'Does this spec fully address the requirements?',
440
+ 'Are there any edge cases not covered?',
441
+ 'Is the scope clear and achievable?'
442
+ ],
443
+ 'post-implementation': [
444
+ 'Have I introduced any bugs or regressions?',
445
+ 'Does the code follow project patterns?',
446
+ 'Is there any code that could be simplified?'
447
+ ],
448
+ 'pre-completion': [
449
+ 'Does this match what the user asked for?',
450
+ 'Have all acceptance criteria been met?',
451
+ 'Are there any loose ends to address?'
452
+ ],
453
+ 'post-failure': [
454
+ 'What caused this failure?',
455
+ 'What can be learned from this?',
456
+ 'How can similar failures be prevented?'
457
+ ]
458
+ };
459
+
460
+ return questions[checkpoint] || [
461
+ 'Is the current approach correct?',
462
+ 'Are there any concerns to address?'
463
+ ];
464
+ }
465
+
466
+ /**
467
+ * Record reflection answer
468
+ */
469
+ function recordReflectionAnswer(taskId, checkpoint, questionIndex, answer) {
470
+ const filePath = path.join(VERIFICATIONS_DIR, 'reflections', `${taskId}-${checkpoint}.json`);
471
+
472
+ if (!fs.existsSync(filePath)) {
473
+ return null;
474
+ }
475
+
476
+ try {
477
+ const reflection = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
478
+ reflection.answers[questionIndex] = {
479
+ answer,
480
+ timestamp: new Date().toISOString()
481
+ };
482
+ fs.writeFileSync(filePath, JSON.stringify(reflection, null, 2), 'utf-8');
483
+ return reflection;
484
+ } catch {
485
+ return null;
486
+ }
487
+ }
488
+
489
+ /**
490
+ * Get all reflections for a task
491
+ */
492
+ function getTaskReflections(taskId) {
493
+ const reflectionsDir = path.join(VERIFICATIONS_DIR, 'reflections');
494
+
495
+ if (!fs.existsSync(reflectionsDir)) {
496
+ return [];
497
+ }
498
+
499
+ const files = fs.readdirSync(reflectionsDir)
500
+ .filter(f => f.startsWith(`${taskId}-`) && f.endsWith('.json'));
501
+
502
+ return files.map(f => {
503
+ try {
504
+ return JSON.parse(fs.readFileSync(path.join(reflectionsDir, f), 'utf-8'));
505
+ } catch {
506
+ return null;
507
+ }
508
+ }).filter(Boolean);
509
+ }
510
+
511
+ // ============================================================
512
+ // Formatting
513
+ // ============================================================
514
+
515
+ /**
516
+ * Format verification result for display
517
+ */
518
+ function formatVerificationResult(result) {
519
+ let output = '';
520
+
521
+ const status = result.allPassed
522
+ ? `${colors.green}✓ VERIFICATION PASSED${colors.reset}`
523
+ : `${colors.red}✗ VERIFICATION FAILED${colors.reset}`;
524
+
525
+ output += `\n${status}\n`;
526
+ output += `Phase: ${result.phase} | Duration: ${result.duration}ms\n\n`;
527
+
528
+ for (const cmd of result.results) {
529
+ const icon = cmd.passed ? `${colors.green}✓${colors.reset}` : `${colors.red}✗${colors.reset}`;
530
+ output += `${icon} ${cmd.description}\n`;
531
+ if (!cmd.passed && cmd.stderr) {
532
+ output += ` ${colors.dim}${cmd.stderr.slice(0, 200)}${colors.reset}\n`;
533
+ }
534
+ }
535
+
536
+ return output;
537
+ }
538
+
539
+ // ============================================================
540
+ // CLI
541
+ // ============================================================
542
+
543
+ function showHelp() {
544
+ console.log(`
545
+ Wogi Flow - File-Based Verification
546
+
547
+ Every phase produces artifacts. Logs are state.
548
+
549
+ Usage:
550
+ flow verify <task-id> [phase]
551
+ flow verify <task-id> --all
552
+ flow verify <task-id> --loop
553
+
554
+ Phases:
555
+ spec Verify spec exists and is valid
556
+ test Run tests (initial)
557
+ implementation Run lint and typecheck
558
+ final Run all quality gates
559
+
560
+ Options:
561
+ --all Run all phase verifications
562
+ --loop Execute full structured loop
563
+ --json Output as JSON
564
+ --help, -h Show this help
565
+
566
+ Examples:
567
+ flow verify wf-abc123 implementation
568
+ flow verify wf-abc123 final
569
+ flow verify wf-abc123 --loop
570
+ `);
571
+ }
572
+
573
+ async function main() {
574
+ const args = process.argv.slice(2);
575
+
576
+ if (args.includes('--help') || args.includes('-h') || args.length === 0) {
577
+ showHelp();
578
+ process.exit(0);
579
+ }
580
+
581
+ const taskId = args[0];
582
+ const phase = args[1] || 'implementation';
583
+ const jsonOutput = args.includes('--json');
584
+ const runAll = args.includes('--all');
585
+ const runLoop = args.includes('--loop');
586
+
587
+ if (runLoop) {
588
+ console.log(`${colors.cyan}Executing structured loop for ${taskId}...${colors.reset}\n`);
589
+ const loopState = await executeStructuredLoop(taskId);
590
+
591
+ if (jsonOutput) {
592
+ console.log(JSON.stringify(loopState, null, 2));
593
+ } else {
594
+ for (const [phaseName, phaseData] of Object.entries(loopState.phases)) {
595
+ const icon = phaseData.status === 'completed' ? '✓' : '✗';
596
+ console.log(`${icon} ${phaseName}: ${phaseData.status}`);
597
+ }
598
+ console.log(`\n${loopState.success ? 'Loop completed successfully' : 'Loop failed'}`);
599
+ }
600
+ } else if (runAll) {
601
+ const phases = ['spec', 'test', 'implementation', 'final'];
602
+ for (const p of phases) {
603
+ console.log(`\n${colors.cyan}Running ${p} verification...${colors.reset}`);
604
+ const result = await runVerification(taskId, p);
605
+ console.log(formatVerificationResult(result));
606
+ }
607
+ } else {
608
+ const result = await runVerification(taskId, phase);
609
+
610
+ if (jsonOutput) {
611
+ console.log(JSON.stringify(result, null, 2));
612
+ } else {
613
+ console.log(formatVerificationResult(result));
614
+ }
615
+ }
616
+ }
617
+
618
+ // ============================================================
619
+ // Exports
620
+ // ============================================================
621
+
622
+ module.exports = {
623
+ runVerification,
624
+ runCommand,
625
+ getDefaultCommands,
626
+ saveVerificationResult,
627
+ loadVerificationResult,
628
+ getAllVerificationResults,
629
+ executeStructuredLoop,
630
+ saveLoopState,
631
+ loadLoopState,
632
+ createReflectionCheckpoint,
633
+ recordReflectionAnswer,
634
+ getTaskReflections,
635
+ getReflectionQuestions,
636
+ formatVerificationResult
637
+ };
638
+
639
+ if (require.main === module) {
640
+ main().catch(err => {
641
+ console.error(`Error: ${err.message}`);
642
+ process.exit(1);
643
+ });
644
+ }