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,400 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Wogi Flow - Interactive Component Confirmation
5
+ *
6
+ * Presents match results to developer and collects decisions
7
+ * for each component (use existing, add variant, create new, skip).
8
+ *
9
+ * Usage:
10
+ * flow figma confirm <match-results.json> # Interactive mode
11
+ * flow figma confirm --auto # Auto-confirm high matches
12
+ */
13
+
14
+ const fs = require('fs');
15
+ const path = require('path');
16
+ const readline = require('readline');
17
+ const { getProjectRoot, colors: c } = require('./flow-utils');
18
+
19
+ const PROJECT_ROOT = getProjectRoot();
20
+ const WORKFLOW_DIR = path.join(PROJECT_ROOT, '.workflow');
21
+ const DECISIONS_PATH = path.join(WORKFLOW_DIR, 'state', 'figma-decisions.json');
22
+
23
+ const sym = {
24
+ check: '✅',
25
+ cross: '❌',
26
+ warning: '⚠️',
27
+ new: '🆕',
28
+ variant: '➕',
29
+ skip: '⏭️',
30
+ match: '🎯'
31
+ };
32
+
33
+ // ============================================================
34
+ // Interactive Confirmer
35
+ // ============================================================
36
+
37
+ class InteractiveConfirmer {
38
+ constructor() {
39
+ this.decisions = [];
40
+ this.rl = null;
41
+ }
42
+
43
+ async confirm(matchResults) {
44
+ this.rl = readline.createInterface({
45
+ input: process.stdin,
46
+ output: process.stdout
47
+ });
48
+
49
+ // Print header
50
+ this.printHeader(matchResults.summary);
51
+
52
+ // Process each component
53
+ for (const match of matchResults.matches) {
54
+ const decision = await this.confirmComponent(match);
55
+ this.decisions.push(decision);
56
+ }
57
+
58
+ this.rl.close();
59
+
60
+ // Print summary
61
+ this.printSummary();
62
+
63
+ // Save decisions
64
+ this.saveDecisions();
65
+
66
+ return this.decisions;
67
+ }
68
+
69
+ printHeader(summary) {
70
+ console.log(`
71
+ ${c.cyan}╔═══════════════════════════════════════════════════════════════════╗
72
+ ║ FIGMA COMPONENT ANALYZER ║
73
+ ║ Interactive Confirmation Flow ║
74
+ ╚═══════════════════════════════════════════════════════════════════╝${c.reset}
75
+
76
+ ${c.bold}Analysis Summary:${c.reset}
77
+ Total components: ${summary.total}
78
+ ${c.green}Exact matches: ${summary.exactMatches}${c.reset}
79
+ ${c.yellow}Strong matches: ${summary.strongMatches}${c.reset}
80
+ ${c.blue}Variant candidates: ${summary.variantCandidates}${c.reset}
81
+ ${c.magenta}New components: ${summary.newComponents}${c.reset}
82
+
83
+ Let's go through each component:
84
+ `);
85
+ }
86
+
87
+ async confirmComponent(match) {
88
+ const { figmaComponent, bestMatch, suggestion } = match;
89
+
90
+ console.log(`\n${'━'.repeat(70)}`);
91
+ console.log(`\n${c.bold}📦 ${figmaComponent.name}${c.reset} (${figmaComponent.type})`);
92
+
93
+ if (!bestMatch) {
94
+ console.log(`\n ${c.dim}No matching components found in codebase${c.reset}`);
95
+ console.log(` Suggestion: ${c.magenta}Create new component${c.reset}`);
96
+
97
+ return this.promptNewComponent(figmaComponent, suggestion);
98
+ }
99
+
100
+ // Show match details
101
+ const score = bestMatch.score;
102
+ const scoreColor = score >= 80 ? c.green : score >= 60 ? c.yellow : c.red;
103
+
104
+ console.log(`\n ${c.bold}Best Match:${c.reset} ${bestMatch.registryComponent.name}`);
105
+ console.log(` ${c.bold}Score:${c.reset} ${scoreColor}${score}%${c.reset}`);
106
+ console.log(` ${c.bold}Path:${c.reset} ${c.dim}${bestMatch.registryComponent.path}${c.reset}`);
107
+
108
+ // Show score breakdown
109
+ console.log(`\n ${c.dim}Score Breakdown:${c.reset}`);
110
+ console.log(` ${c.dim}├─ CSS: ${bestMatch.breakdown.css}%${c.reset}`);
111
+ console.log(` ${c.dim}├─ Structure: ${bestMatch.breakdown.structure}%${c.reset}`);
112
+ console.log(` ${c.dim}├─ Naming: ${bestMatch.breakdown.naming}%${c.reset}`);
113
+ console.log(` ${c.dim}└─ Behavior: ${bestMatch.breakdown.behavior}%${c.reset}`);
114
+
115
+ // Show differences if any
116
+ if (bestMatch.differences && bestMatch.differences.length > 0) {
117
+ console.log(`\n ${c.yellow}Differences:${c.reset}`);
118
+ bestMatch.differences.forEach(diff => {
119
+ console.log(` ${c.dim}• ${diff.description}${c.reset}`);
120
+ });
121
+ }
122
+
123
+ // Show suggestion
124
+ console.log(`\n ${c.bold}Suggestion:${c.reset} ${this.formatSuggestion(suggestion)}`);
125
+
126
+ // Prompt for decision
127
+ return this.promptDecision(figmaComponent, bestMatch, suggestion);
128
+ }
129
+
130
+ formatSuggestion(suggestion) {
131
+ switch (suggestion.action) {
132
+ case 'use':
133
+ return `${c.green}${sym.check} Use existing ${suggestion.component}${c.reset}`;
134
+ case 'use-with-adjustments':
135
+ return `${c.yellow}${sym.warning} Use ${suggestion.component} with adjustments${c.reset}`;
136
+ case 'add-variant':
137
+ return `${c.blue}${sym.variant} Add variant "${suggestion.suggestedVariantName || 'new'}" to ${suggestion.component}${c.reset}`;
138
+ case 'create-new':
139
+ return `${c.magenta}${sym.new} Create new component${c.reset}`;
140
+ default:
141
+ return suggestion.action;
142
+ }
143
+ }
144
+
145
+ async promptDecision(figmaComponent, bestMatch, suggestion) {
146
+ console.log(`\n ${c.bold}Options:${c.reset}`);
147
+ console.log(` ${c.cyan}[1]${c.reset} ${sym.check} Use existing ${bestMatch.registryComponent.name}`);
148
+ console.log(` ${c.cyan}[2]${c.reset} ${sym.variant} Add as variant to ${bestMatch.registryComponent.name}`);
149
+ console.log(` ${c.cyan}[3]${c.reset} ${sym.new} Create new component`);
150
+ console.log(` ${c.cyan}[4]${c.reset} ${sym.skip} Skip - I'll handle manually`);
151
+ console.log(` ${c.cyan}[Enter]${c.reset} Accept suggestion`);
152
+
153
+ const choice = await this.prompt('\n Your choice: ');
154
+
155
+ let action;
156
+ switch (choice.trim()) {
157
+ case '1':
158
+ action = 'use';
159
+ break;
160
+ case '2':
161
+ action = 'add-variant';
162
+ break;
163
+ case '3':
164
+ action = 'create-new';
165
+ break;
166
+ case '4':
167
+ action = 'skip';
168
+ break;
169
+ case '':
170
+ action = suggestion.action;
171
+ break;
172
+ default:
173
+ console.log(` ${c.dim}Invalid choice, using suggestion${c.reset}`);
174
+ action = suggestion.action;
175
+ }
176
+
177
+ // Get additional info based on action
178
+ let extraInfo = {};
179
+
180
+ if (action === 'add-variant') {
181
+ const defaultVariant = suggestion.suggestedVariantName || 'variant';
182
+ const variantName = await this.prompt(` Variant name [${defaultVariant}]: `);
183
+ extraInfo.variantName = variantName.trim() || defaultVariant;
184
+ }
185
+
186
+ if (action === 'create-new') {
187
+ const suggestedName = suggestion.suggestedName || this.suggestName(figmaComponent.name);
188
+ const componentName = await this.prompt(` Component name [${suggestedName}]: `);
189
+ extraInfo.componentName = componentName.trim() || suggestedName;
190
+ }
191
+
192
+ console.log(`\n ${c.green}✓ ${this.formatAction(action, bestMatch?.registryComponent, extraInfo)}${c.reset}`);
193
+
194
+ return {
195
+ figmaComponent: figmaComponent,
196
+ action: action,
197
+ existingComponent: action !== 'create-new' && action !== 'skip' ? bestMatch.registryComponent : null,
198
+ score: bestMatch?.score || 0,
199
+ ...extraInfo
200
+ };
201
+ }
202
+
203
+ async promptNewComponent(figmaComponent, suggestion) {
204
+ console.log(`\n ${c.bold}Options:${c.reset}`);
205
+ console.log(` ${c.cyan}[1]${c.reset} ${sym.new} Create new component`);
206
+ console.log(` ${c.cyan}[2]${c.reset} ${sym.skip} Skip - I'll handle manually`);
207
+
208
+ const choice = await this.prompt('\n Your choice [1]: ');
209
+
210
+ if (choice.trim() === '2') {
211
+ return {
212
+ figmaComponent: figmaComponent,
213
+ action: 'skip'
214
+ };
215
+ }
216
+
217
+ const suggestedName = suggestion.suggestedName || this.suggestName(figmaComponent.name);
218
+ const componentName = await this.prompt(` Component name [${suggestedName}]: `);
219
+
220
+ console.log(`\n ${c.green}✓ Will create new component: ${componentName || suggestedName}${c.reset}`);
221
+
222
+ return {
223
+ figmaComponent: figmaComponent,
224
+ action: 'create-new',
225
+ componentName: componentName.trim() || suggestedName
226
+ };
227
+ }
228
+
229
+ formatAction(action, existingComponent, extraInfo) {
230
+ switch (action) {
231
+ case 'use':
232
+ return `Will use existing ${existingComponent?.name || 'component'}`;
233
+ case 'use-with-adjustments':
234
+ return `Will use ${existingComponent?.name || 'component'} with adjustments`;
235
+ case 'add-variant':
236
+ return `Will add variant "${extraInfo.variantName}" to ${existingComponent?.name || 'component'}`;
237
+ case 'create-new':
238
+ return `Will create new component: ${extraInfo.componentName}`;
239
+ case 'skip':
240
+ return `Skipped - handle manually`;
241
+ default:
242
+ return action;
243
+ }
244
+ }
245
+
246
+ suggestName(figmaName) {
247
+ return (figmaName || 'Component')
248
+ .replace(/[^a-zA-Z0-9\s]/g, '')
249
+ .split(/\s+/)
250
+ .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
251
+ .join('');
252
+ }
253
+
254
+ prompt(question) {
255
+ return new Promise(resolve => {
256
+ this.rl.question(question, resolve);
257
+ });
258
+ }
259
+
260
+ printSummary() {
261
+ const summary = {
262
+ use: 0,
263
+ 'use-with-adjustments': 0,
264
+ 'add-variant': 0,
265
+ 'create-new': 0,
266
+ skip: 0
267
+ };
268
+
269
+ this.decisions.forEach(d => {
270
+ summary[d.action] = (summary[d.action] || 0) + 1;
271
+ });
272
+
273
+ console.log(`
274
+
275
+ ${'═'.repeat(70)}
276
+
277
+ ${c.bold}CONFIRMATION SUMMARY${c.reset}
278
+
279
+ ${c.green}${sym.check} Use existing:${c.reset} ${summary.use + summary['use-with-adjustments']}
280
+ ${c.blue}${sym.variant} Add variant:${c.reset} ${summary['add-variant']}
281
+ ${c.magenta}${sym.new} Create new:${c.reset} ${summary['create-new']}
282
+ ${c.dim}${sym.skip} Skipped:${c.reset} ${summary.skip}
283
+
284
+ `);
285
+ }
286
+
287
+ saveDecisions() {
288
+ const stateDir = path.dirname(DECISIONS_PATH);
289
+ if (!fs.existsSync(stateDir)) {
290
+ fs.mkdirSync(stateDir, { recursive: true });
291
+ }
292
+
293
+ fs.writeFileSync(DECISIONS_PATH, JSON.stringify({
294
+ timestamp: new Date().toISOString(),
295
+ decisions: this.decisions
296
+ }, null, 2));
297
+
298
+ console.log(`${c.dim}Decisions saved to: ${path.relative(PROJECT_ROOT, DECISIONS_PATH)}${c.reset}`);
299
+ }
300
+ }
301
+
302
+ // ============================================================
303
+ // Auto-Confirm Mode
304
+ // ============================================================
305
+
306
+ class AutoConfirmer {
307
+ constructor(threshold = 80) {
308
+ this.threshold = threshold;
309
+ }
310
+
311
+ confirm(matchResults) {
312
+ const decisions = [];
313
+
314
+ for (const match of matchResults.matches) {
315
+ const { figmaComponent, bestMatch, suggestion } = match;
316
+
317
+ let decision;
318
+
319
+ if (!bestMatch || bestMatch.score < this.threshold) {
320
+ // Create new for low/no matches
321
+ decision = {
322
+ figmaComponent: figmaComponent,
323
+ action: 'create-new',
324
+ componentName: suggestion.suggestedName || figmaComponent.name
325
+ };
326
+ } else if (bestMatch.score >= 95) {
327
+ // Use directly for very high matches
328
+ decision = {
329
+ figmaComponent: figmaComponent,
330
+ action: 'use',
331
+ existingComponent: bestMatch.registryComponent,
332
+ score: bestMatch.score
333
+ };
334
+ } else {
335
+ // Use with adjustments for medium-high matches
336
+ decision = {
337
+ figmaComponent: figmaComponent,
338
+ action: 'use-with-adjustments',
339
+ existingComponent: bestMatch.registryComponent,
340
+ score: bestMatch.score,
341
+ differences: bestMatch.differences
342
+ };
343
+ }
344
+
345
+ decisions.push(decision);
346
+ }
347
+
348
+ return decisions;
349
+ }
350
+ }
351
+
352
+ // ============================================================
353
+ // CLI
354
+ // ============================================================
355
+
356
+ async function main() {
357
+ const [,, input, ...args] = process.argv;
358
+
359
+ const autoMode = args.includes('--auto');
360
+
361
+ if (!input || !fs.existsSync(input)) {
362
+ if (input && input !== '--auto') {
363
+ console.error(`File not found: ${input}`);
364
+ }
365
+ console.log(`
366
+ Wogi Flow - Interactive Component Confirmation
367
+
368
+ Usage:
369
+ flow figma confirm <match-results.json> Interactive mode
370
+ flow figma confirm <match-results.json> --auto Auto-confirm high matches
371
+
372
+ Example:
373
+ ./scripts/flow-figma-match.js figma-data.json > matches.json
374
+ ./scripts/flow-figma-confirm.js matches.json
375
+ `);
376
+ process.exit(1);
377
+ }
378
+
379
+ const matchResults = JSON.parse(fs.readFileSync(input, 'utf-8'));
380
+
381
+ let decisions;
382
+
383
+ if (autoMode) {
384
+ const confirmer = new AutoConfirmer();
385
+ decisions = confirmer.confirm(matchResults);
386
+ console.log(JSON.stringify({ decisions }, null, 2));
387
+ } else {
388
+ const confirmer = new InteractiveConfirmer();
389
+ decisions = await confirmer.confirm(matchResults);
390
+ }
391
+ }
392
+
393
+ module.exports = { InteractiveConfirmer, AutoConfirmer };
394
+
395
+ if (require.main === module) {
396
+ main().catch(err => {
397
+ console.error(`Error: ${err.message}`);
398
+ process.exit(1);
399
+ });
400
+ }