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,434 @@
1
+ /**
2
+ * Claude Code Bridge
3
+ *
4
+ * Generates .claude/ folder structure and CLAUDE.md from .workflow/ configuration.
5
+ *
6
+ * Sync targets:
7
+ * - .workflow/skills/ → .claude/skills/
8
+ * - .workflow/rules/ → .claude/rules/
9
+ * - .workflow/config.json + templates → CLAUDE.md
10
+ */
11
+
12
+ const fs = require('fs');
13
+ const path = require('path');
14
+ const BaseBridge = require('./base-bridge');
15
+
16
+ class ClaudeBridge extends BaseBridge {
17
+ constructor(options = {}) {
18
+ super('claude-code', options);
19
+
20
+ this.cliFolder = '.claude';
21
+ this.rulesFile = 'CLAUDE.md';
22
+ this.skillsPath = '.claude/skills';
23
+ this.rulesPath = '.claude/rules';
24
+ }
25
+
26
+ getCliFolder() {
27
+ return this.cliFolder;
28
+ }
29
+
30
+ getRulesFileName() {
31
+ return this.rulesFile;
32
+ }
33
+
34
+ getSkillsPath() {
35
+ return this.skillsPath;
36
+ }
37
+
38
+ getRulesPath() {
39
+ return this.rulesPath;
40
+ }
41
+
42
+ /**
43
+ * Generate CLAUDE.md content from config
44
+ * @param {Object} config - The workflow config
45
+ * @returns {string} Generated CLAUDE.md content
46
+ */
47
+ generateRulesContent(config) {
48
+ const projectName = config.projectName || 'Project';
49
+
50
+ // Check if custom template exists
51
+ const templatePath = path.join(this.projectDir, this.workflowDir, 'templates', 'claude-md.hbs');
52
+ if (fs.existsSync(templatePath)) {
53
+ return this.generateFromTemplate(templatePath, config);
54
+ }
55
+
56
+ // Default template - comprehensive CLAUDE.md
57
+ return this.generateDefaultClaudeMd(config);
58
+ }
59
+
60
+ /**
61
+ * Generate CLAUDE.md from Handlebars template
62
+ */
63
+ generateFromTemplate(templatePath, config) {
64
+ const template = fs.readFileSync(templatePath, 'utf-8');
65
+
66
+ // Simple template variable replacement (not full Handlebars)
67
+ let content = template;
68
+
69
+ // Replace {{variable}} patterns
70
+ content = content.replace(/\{\{(\w+)\}\}/g, (match, key) => {
71
+ return config[key] || match;
72
+ });
73
+
74
+ // Replace {{config.path.to.value}} patterns
75
+ content = content.replace(/\{\{config\.([^}]+)\}\}/g, (match, path) => {
76
+ const value = this.getNestedValue(config, path);
77
+ return value !== undefined ? String(value) : match;
78
+ });
79
+
80
+ return content;
81
+ }
82
+
83
+ /**
84
+ * Generate default CLAUDE.md when no template exists
85
+ */
86
+ generateDefaultClaudeMd(config) {
87
+ const projectName = config.projectName || 'Project';
88
+ const skills = config.skills?.installed || [];
89
+
90
+ const sections = [];
91
+
92
+ // Header
93
+ sections.push(`# Project Instructions
94
+
95
+ You are an AI development assistant using the Wogi Flow methodology v1.9. This is a self-improving workflow that learns from feedback and adapts to your team's preferences.
96
+
97
+ ---`);
98
+
99
+ // Task Gating Section (if strict mode enabled)
100
+ if (config.enforcement?.strictMode) {
101
+ sections.push(`
102
+ ## Task Gating (MANDATORY)
103
+
104
+ **STOP. Before doing ANY implementation work, follow these steps:**
105
+
106
+ 1. **Is this an implementation request?** (Adding, fixing, creating code)
107
+ - If NO → Proceed normally
108
+ - If YES → Continue to step 2
109
+
110
+ 2. **Does a task already exist?**
111
+ - Check \`.workflow/state/ready.json\`
112
+ - If YES → Use \`/wogi-start TASK-XXX\`
113
+ - If NO → Continue to step 3
114
+
115
+ 3. **Assess task size:**
116
+ - **Small** (< 3 files): Create task inline
117
+ - **Medium/Large** (3+ files): Create story first with \`/wogi-story\`
118
+
119
+ ---`);
120
+ }
121
+
122
+ // Quick Start
123
+ sections.push(`
124
+ ## Quick Start
125
+
126
+ \`\`\`bash
127
+ cat .workflow/config.json # Read config
128
+ cat .workflow/state/ready.json # Check tasks
129
+ cat .workflow/state/decisions.md # Project rules
130
+ \`\`\`
131
+
132
+ ---`);
133
+
134
+ // Essential Commands
135
+ sections.push(`
136
+ ## Essential Commands
137
+
138
+ | Command | Purpose |
139
+ |---------|---------|
140
+ | \`/wogi-ready\` | Show available tasks |
141
+ | \`/wogi-start TASK-X\` | Start task (self-completing loop) |
142
+ | \`/wogi-story "title"\` | Create story with acceptance criteria |
143
+ | \`/wogi-status\` | Project overview |
144
+ | \`/wogi-health\` | Check workflow health |
145
+
146
+ ---`);
147
+
148
+ // Auto-Validation
149
+ sections.push(`
150
+ ## Auto-Validation (CRITICAL)
151
+
152
+ After editing ANY TypeScript/JavaScript file:
153
+ \`\`\`bash
154
+ npx tsc --noEmit 2>&1 | head -20
155
+ npx eslint [file] --fix
156
+ \`\`\`
157
+
158
+ **Do NOT edit another file until current file passes validation.**
159
+
160
+ ---`);
161
+
162
+ // Skills Section
163
+ if (skills.length > 0) {
164
+ sections.push(`
165
+ ## Installed Skills
166
+
167
+ ${skills.map(s => `- ${s}`).join('\n')}
168
+
169
+ Check \`.claude/skills/[name]/skill.md\` for skill-specific guidance.
170
+
171
+ ---`);
172
+ }
173
+
174
+ // File Locations
175
+ sections.push(`
176
+ ## File Locations
177
+
178
+ | What | Where |
179
+ |------|-------|
180
+ | Config | \`.workflow/config.json\` |
181
+ | Tasks | \`.workflow/state/ready.json\` |
182
+ | Logs | \`.workflow/state/request-log.md\` |
183
+ | Components | \`.workflow/state/app-map.md\` |
184
+ | Rules | \`.workflow/state/decisions.md\` |
185
+ | Progress | \`.workflow/state/progress.md\` |
186
+
187
+ ---`);
188
+
189
+ // Component Reuse
190
+ sections.push(`
191
+ ## Component Reuse
192
+
193
+ **Before creating ANY component:**
194
+ 1. Check \`app-map.md\`
195
+ 2. Search codebase for existing
196
+ 3. Priority: Use existing → Add variant → Extend → Create new (last resort)
197
+
198
+ ---`);
199
+
200
+ // Commit Behavior
201
+ sections.push(`
202
+ ## Commit Behavior
203
+
204
+ Check \`config.json → commits\` before committing:
205
+ - Features require user approval (default)
206
+ - Small fixes (≤${config.commits?.smallFixThreshold || 3} files) can auto-commit
207
+ - Always show git diff before committing features/refactors
208
+
209
+ ---`);
210
+
211
+ // Context Management
212
+ sections.push(`
213
+ ## Context Management
214
+
215
+ Use \`/wogi-compact\` when:
216
+ - After completing 2-3 tasks
217
+ - After 15-20 messages
218
+ - Before starting large tasks
219
+
220
+ ---`);
221
+
222
+ // Footer
223
+ sections.push(`
224
+ ## Generated by CLI Bridge
225
+
226
+ This file was generated by the Wogi Flow CLI bridge.
227
+ Edit \`.workflow/templates/claude-md.hbs\` to customize.
228
+ Run \`flow bridge sync\` to regenerate.
229
+
230
+ Last synced: ${new Date().toISOString()}
231
+ `);
232
+
233
+ return sections.join('\n');
234
+ }
235
+
236
+ /**
237
+ * CLI-specific setup for Claude Code
238
+ */
239
+ async setupCliSpecific(config) {
240
+ // Ensure .claude directory structure
241
+ const clauePath = path.join(this.projectDir, this.cliFolder);
242
+
243
+ // Create standard directories
244
+ const dirs = ['commands', 'docs', 'rules', 'skills'];
245
+ for (const dir of dirs) {
246
+ const dirPath = path.join(clauePath, dir);
247
+ if (!fs.existsSync(dirPath)) {
248
+ fs.mkdirSync(dirPath, { recursive: true });
249
+ this.log(`Created ${this.cliFolder}/${dir}/`);
250
+ }
251
+ }
252
+
253
+ // Copy commands from .workflow/commands if they exist
254
+ const workflowCommands = path.join(this.projectDir, this.workflowDir, 'commands');
255
+ const claudeCommands = path.join(clauePath, 'commands');
256
+
257
+ if (fs.existsSync(workflowCommands)) {
258
+ const commands = fs.readdirSync(workflowCommands).filter(f => f.endsWith('.md'));
259
+ for (const cmd of commands) {
260
+ fs.copyFileSync(
261
+ path.join(workflowCommands, cmd),
262
+ path.join(claudeCommands, cmd)
263
+ );
264
+ this.log(`Synced command: ${cmd}`);
265
+ }
266
+ }
267
+
268
+ // Ensure hot-reload compatibility: skills in .claude/skills
269
+ // This is already handled by syncSkills() in base class
270
+ }
271
+
272
+ /**
273
+ * Get nested value from object using dot notation
274
+ */
275
+ getNestedValue(obj, path) {
276
+ return path.split('.').reduce((acc, part) => acc && acc[part], obj);
277
+ }
278
+
279
+ /**
280
+ * Generate settings.local.json with wildcard permissions
281
+ * Claude Code 2.1.0+ supports wildcards like Bash(npm *)
282
+ */
283
+ generateSettings(config) {
284
+ const projectDir = this.projectDir;
285
+
286
+ // Base wildcard permissions - covers most common use cases
287
+ const wildcardPermissions = [
288
+ // Package managers
289
+ 'Bash(npm *)',
290
+ 'Bash(npx *)',
291
+ 'Bash(yarn *)',
292
+ 'Bash(pnpm *)',
293
+ 'Bash(pip *)',
294
+ 'Bash(python *)',
295
+ 'Bash(python3 *)',
296
+
297
+ // Git operations
298
+ 'Bash(git status)',
299
+ 'Bash(git status *)',
300
+ 'Bash(git diff *)',
301
+ 'Bash(git log *)',
302
+ 'Bash(git branch *)',
303
+ 'Bash(git checkout *)',
304
+ 'Bash(git add *)',
305
+ 'Bash(git commit *)',
306
+ 'Bash(git push *)',
307
+ 'Bash(git pull *)',
308
+ 'Bash(git fetch *)',
309
+ 'Bash(git reset *)',
310
+ 'Bash(git restore *)',
311
+ 'Bash(git show *)',
312
+ 'Bash(git rm *)',
313
+ 'Bash(git ls-files *)',
314
+ 'Bash(git check-ignore *)',
315
+
316
+ // GitHub CLI
317
+ 'Bash(gh pr *)',
318
+ 'Bash(gh issue *)',
319
+ 'Bash(gh api *)',
320
+
321
+ // Flow scripts
322
+ `Bash(${path.join(projectDir, 'scripts/flow')} *)`,
323
+ 'Bash(./scripts/flow *)',
324
+ 'Bash(./scripts/flow)',
325
+
326
+ // Common utilities
327
+ 'Bash(ls *)',
328
+ 'Bash(tree *)',
329
+ 'Bash(cat *)',
330
+ 'Bash(head *)',
331
+ 'Bash(tail *)',
332
+ 'Bash(wc *)',
333
+ 'Bash(grep *)',
334
+ 'Bash(find *)',
335
+ 'Bash(chmod +x *)', // Only make executable, not arbitrary permissions
336
+ 'Bash(node *)',
337
+ 'Bash(bash *)',
338
+ 'Bash(open *)',
339
+ 'Bash(test *)',
340
+
341
+ // AWS - Read-only and safe operations
342
+ 'Bash(aws s3 ls *)',
343
+ 'Bash(aws s3 cp *)',
344
+ 'Bash(aws sts get-caller-identity)',
345
+ 'Bash(aws sts get-caller-identity *)',
346
+ 'Bash(aws configure list)',
347
+ 'Bash(aws --version)',
348
+
349
+ // Terraform - Safe planning and validation operations
350
+ 'Bash(terraform plan *)',
351
+ 'Bash(terraform fmt *)',
352
+ 'Bash(terraform validate *)',
353
+ 'Bash(terraform init *)',
354
+ 'Bash(terraform show *)',
355
+ 'Bash(terraform output *)',
356
+ 'Bash(terraform version)',
357
+
358
+ // Database - Project-scoped
359
+ 'Bash(sqlite3 *.db *)',
360
+ 'Bash(sqlite3 *.sqlite *)',
361
+
362
+ // Web fetch domains
363
+ 'WebFetch(domain:github.com)',
364
+ 'WebFetch(domain:api.github.com)',
365
+ 'WebFetch(domain:raw.githubusercontent.com)',
366
+
367
+ // Web search
368
+ 'WebSearch',
369
+
370
+ // Skills
371
+ 'Skill(wogi-*)',
372
+ ];
373
+
374
+ // Additional domains from config
375
+ const additionalDomains = config.permissions?.allowedDomains || [];
376
+ for (const domain of additionalDomains) {
377
+ wildcardPermissions.push(`WebFetch(domain:${domain})`);
378
+ }
379
+
380
+ // Additional custom permissions from config (for advanced users)
381
+ const customPermissions = config.permissions?.custom || [];
382
+ for (const perm of customPermissions) {
383
+ if (!wildcardPermissions.includes(perm)) {
384
+ wildcardPermissions.push(perm);
385
+ }
386
+ }
387
+
388
+ return {
389
+ permissions: {
390
+ allow: wildcardPermissions,
391
+ },
392
+ respectGitignore: true,
393
+ _wogiFlowManaged: true,
394
+ _wogiFlowVersion: '2.0.0',
395
+ _generatedAt: new Date().toISOString(),
396
+ };
397
+ }
398
+
399
+ /**
400
+ * Sync settings.local.json with wildcard permissions
401
+ * Preserves hooks and other custom settings
402
+ */
403
+ syncSettings(config) {
404
+ const settingsPath = path.join(this.projectDir, this.cliFolder, 'settings.local.json');
405
+
406
+ let existingSettings = {};
407
+ if (fs.existsSync(settingsPath)) {
408
+ try {
409
+ existingSettings = JSON.parse(fs.readFileSync(settingsPath, 'utf-8'));
410
+ } catch (e) {
411
+ this.log(`Warning: Could not parse existing settings.local.json`);
412
+ }
413
+ }
414
+
415
+ const newSettings = this.generateSettings(config);
416
+
417
+ // Merge: keep existing hooks, use new permissions
418
+ const mergedSettings = {
419
+ permissions: newSettings.permissions,
420
+ respectGitignore: newSettings.respectGitignore,
421
+ hooks: existingSettings.hooks || {},
422
+ _wogiFlowManaged: newSettings._wogiFlowManaged,
423
+ _wogiFlowVersion: newSettings._wogiFlowVersion,
424
+ _generatedAt: newSettings._generatedAt,
425
+ };
426
+
427
+ fs.writeFileSync(settingsPath, JSON.stringify(mergedSettings, null, 2));
428
+ this.log(`Synced settings.local.json with wildcard permissions (${newSettings.permissions.allow.length} rules)`);
429
+
430
+ return mergedSettings;
431
+ }
432
+ }
433
+
434
+ module.exports = ClaudeBridge;
@@ -0,0 +1,130 @@
1
+ /**
2
+ * CLI Bridges - Entry Point
3
+ *
4
+ * Provides a unified interface for loading and using CLI bridges.
5
+ *
6
+ * Usage:
7
+ * const { getBridge, syncBridge } = require('./.workflow/bridges');
8
+ *
9
+ * // Get the bridge for current CLI type
10
+ * const bridge = getBridge();
11
+ *
12
+ * // Sync files from .workflow/ to CLI-specific folder
13
+ * await syncBridge();
14
+ */
15
+
16
+ const fs = require('fs');
17
+ const path = require('path');
18
+
19
+ // Lazy-load bridges to avoid circular dependencies
20
+ let bridges = null;
21
+
22
+ /**
23
+ * Load available bridge implementations
24
+ */
25
+ function loadBridges() {
26
+ if (bridges) return bridges;
27
+
28
+ bridges = {
29
+ 'claude-code': () => require('./claude-bridge'),
30
+ // Add more bridges as they are implemented
31
+ // 'gemini-cli': () => require('./gemini-bridge'),
32
+ // 'opencode': () => require('./opencode-bridge'),
33
+ };
34
+
35
+ return bridges;
36
+ }
37
+
38
+ /**
39
+ * Read CLI type from config
40
+ * @param {string} projectDir - Project root directory
41
+ * @returns {string} CLI type (defaults to 'claude-code')
42
+ */
43
+ function getCliType(projectDir = process.cwd()) {
44
+ const configPath = path.join(projectDir, '.workflow', 'config.json');
45
+
46
+ if (!fs.existsSync(configPath)) {
47
+ return 'claude-code'; // Default
48
+ }
49
+
50
+ try {
51
+ const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
52
+ return config.cli?.type || 'claude-code';
53
+ } catch {
54
+ return 'claude-code';
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Get the bridge instance for the current CLI type
60
+ * @param {Object} options - Options to pass to bridge constructor
61
+ * @param {string} options.projectDir - Project root directory
62
+ * @param {boolean} options.verbose - Enable verbose logging
63
+ * @returns {BaseBridge} Bridge instance
64
+ */
65
+ function getBridge(options = {}) {
66
+ const projectDir = options.projectDir || process.cwd();
67
+ const cliType = getCliType(projectDir);
68
+
69
+ loadBridges();
70
+
71
+ const BridgeLoader = bridges[cliType];
72
+ if (!BridgeLoader) {
73
+ // If no specific bridge exists, return null (manual mode)
74
+ console.warn(`No bridge available for CLI type: ${cliType}`);
75
+ return null;
76
+ }
77
+
78
+ const BridgeClass = BridgeLoader();
79
+ return new BridgeClass({
80
+ projectDir,
81
+ verbose: options.verbose || false
82
+ });
83
+ }
84
+
85
+ /**
86
+ * Sync the current CLI bridge
87
+ * @param {Object} options - Options
88
+ * @returns {Object} Sync result
89
+ */
90
+ async function syncBridge(options = {}) {
91
+ const bridge = getBridge(options);
92
+
93
+ if (!bridge) {
94
+ return {
95
+ success: false,
96
+ error: 'No bridge available for current CLI type',
97
+ cliType: getCliType(options.projectDir)
98
+ };
99
+ }
100
+
101
+ return await bridge.sync();
102
+ }
103
+
104
+ /**
105
+ * List available bridge types
106
+ * @returns {string[]} Array of available CLI types
107
+ */
108
+ function listAvailableBridges() {
109
+ loadBridges();
110
+ return Object.keys(bridges);
111
+ }
112
+
113
+ /**
114
+ * Check if a bridge is available for the given CLI type
115
+ * @param {string} cliType - CLI type to check
116
+ * @returns {boolean}
117
+ */
118
+ function isBridgeAvailable(cliType) {
119
+ loadBridges();
120
+ return cliType in bridges;
121
+ }
122
+
123
+ module.exports = {
124
+ getBridge,
125
+ syncBridge,
126
+ getCliType,
127
+ listAvailableBridges,
128
+ isBridgeAvailable,
129
+ BaseBridge: require('./base-bridge')
130
+ };