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
package/bin/flow ADDED
@@ -0,0 +1,205 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Wogi Flow CLI Entry Point
5
+ *
6
+ * This is the main entry point for the `flow` command when installed globally via npm.
7
+ * It handles both global commands (init, upgrade, version) and project-local commands
8
+ * by delegating to the project's scripts/flow when in a project context.
9
+ *
10
+ * Usage:
11
+ * flow init # Initialize a new project
12
+ * flow upgrade # Upgrade an existing project
13
+ * flow --version # Show version
14
+ * flow <command> # Project commands (when in a project)
15
+ */
16
+
17
+ const path = require('path');
18
+ const fs = require('fs');
19
+ const { spawn } = require('child_process');
20
+
21
+ // Package info
22
+ const packageJson = require('../package.json');
23
+ const VERSION = packageJson.version;
24
+
25
+ // Global commands that don't require a project context
26
+ const GLOBAL_COMMANDS = ['init', 'upgrade', 'version', '--version', '-v', '--help', '-h', 'skill', 'channel'];
27
+
28
+ /**
29
+ * Find the project root by looking for .workflow directory
30
+ * @returns {string|null} Project root path or null if not in a project
31
+ */
32
+ function findProjectRoot() {
33
+ let dir = process.cwd();
34
+ const root = path.parse(dir).root;
35
+
36
+ while (dir !== root) {
37
+ if (fs.existsSync(path.join(dir, '.workflow'))) {
38
+ return dir;
39
+ }
40
+ dir = path.dirname(dir);
41
+ }
42
+
43
+ return null;
44
+ }
45
+
46
+ /**
47
+ * Execute a project-local flow command
48
+ * @param {string} projectRoot - Project root directory
49
+ * @param {string[]} args - Command arguments
50
+ */
51
+ function executeProjectCommand(projectRoot, args) {
52
+ const projectFlow = path.join(projectRoot, 'scripts', 'flow');
53
+
54
+ if (!fs.existsSync(projectFlow)) {
55
+ console.error('Error: scripts/flow not found in project');
56
+ console.error('Run `flow upgrade` to update the project structure');
57
+ process.exit(1);
58
+ }
59
+
60
+ // Spawn the project's flow script
61
+ // Note: shell: false (default) prevents command injection
62
+ const child = spawn(projectFlow, args, {
63
+ cwd: projectRoot,
64
+ stdio: 'inherit'
65
+ });
66
+
67
+ child.on('exit', (code) => {
68
+ process.exit(code || 0);
69
+ });
70
+
71
+ child.on('error', (err) => {
72
+ console.error(`Failed to execute: ${err.message}`);
73
+ process.exit(1);
74
+ });
75
+ }
76
+
77
+ /**
78
+ * Show version information
79
+ */
80
+ function showVersion() {
81
+ console.log(`wogi-flow v${VERSION}`);
82
+ }
83
+
84
+ /**
85
+ * Show help information
86
+ */
87
+ function showHelp() {
88
+ console.log(`
89
+ Wogi Flow v${VERSION}
90
+ AI-powered development workflow management
91
+
92
+ Usage: flow <command> [options]
93
+
94
+ Global Commands:
95
+ init Initialize Wogi Flow in a new project
96
+ upgrade Upgrade an existing project to latest version
97
+ --version, -v Show version number
98
+ --help, -h Show this help message
99
+
100
+ Project Commands (run in a project directory):
101
+ status Show project status
102
+ ready Show available tasks
103
+ start <task> Start working on a task
104
+ story "<title>" Create a new story
105
+ health Check workflow health
106
+ models Model management commands
107
+ ... and many more
108
+
109
+ For project command help, run: flow --help (in a project directory)
110
+
111
+ Examples:
112
+ flow init # Set up Wogi Flow in current directory
113
+ flow init --cli claude # Initialize with Claude Code
114
+ flow upgrade # Upgrade project to latest version
115
+ flow status # Show project overview (in project)
116
+
117
+ Documentation: https://github.com/Wogi-Git/wogi-flow
118
+ `);
119
+ }
120
+
121
+ /**
122
+ * Main entry point
123
+ */
124
+ function main() {
125
+ const args = process.argv.slice(2);
126
+ const command = args[0];
127
+
128
+ // Handle version flag
129
+ if (command === '--version' || command === '-v' || command === 'version') {
130
+ showVersion();
131
+ return;
132
+ }
133
+
134
+ // Handle help flag
135
+ if (command === '--help' || command === '-h' || !command) {
136
+ const projectRoot = findProjectRoot();
137
+ if (projectRoot && command !== '--help' && command !== '-h') {
138
+ // In a project without args - show project help
139
+ executeProjectCommand(projectRoot, ['--help']);
140
+ } else {
141
+ showHelp();
142
+ }
143
+ return;
144
+ }
145
+
146
+ // Handle global commands
147
+ if (command === 'init') {
148
+ // Load and run installer
149
+ const installer = require('../lib/installer');
150
+ installer.init(args.slice(1));
151
+ return;
152
+ }
153
+
154
+ if (command === 'upgrade') {
155
+ // Load and run upgrader
156
+ const upgrader = require('../lib/upgrader');
157
+ upgrader.upgrade(args.slice(1));
158
+ return;
159
+ }
160
+
161
+ if (command === 'skill') {
162
+ // Skill registry commands
163
+ const projectRoot = findProjectRoot();
164
+ if (!projectRoot && args[1] !== 'list') {
165
+ console.error('Error: Not in a Wogi Flow project');
166
+ console.error('Use `flow init` to initialize a new project');
167
+ process.exit(1);
168
+ }
169
+ if (projectRoot) {
170
+ // In project context - delegate to project scripts
171
+ executeProjectCommand(projectRoot, args);
172
+ } else {
173
+ // Outside project - only allow list
174
+ const skillRegistry = require('../lib/skill-registry');
175
+ skillRegistry.skill(args.slice(1));
176
+ }
177
+ return;
178
+ }
179
+
180
+ if (command === 'channel') {
181
+ // Release channel management
182
+ const releaseChannel = require('../lib/release-channel');
183
+ releaseChannel.channel(args.slice(1));
184
+ return;
185
+ }
186
+
187
+ // For all other commands, try to find project context
188
+ const projectRoot = findProjectRoot();
189
+
190
+ if (!projectRoot) {
191
+ console.error('Error: Not in a Wogi Flow project');
192
+ console.error('');
193
+ console.error('To initialize a new project:');
194
+ console.error(' flow init');
195
+ console.error('');
196
+ console.error('To see all options:');
197
+ console.error(' flow --help');
198
+ process.exit(1);
199
+ }
200
+
201
+ // Execute project-local command
202
+ executeProjectCommand(projectRoot, args);
203
+ }
204
+
205
+ main();
package/lib/index.js ADDED
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Wogi Flow Library Index
5
+ *
6
+ * Main entry point for the wogi-flow package.
7
+ * Exports all public modules for programmatic usage.
8
+ *
9
+ * @module wogi-flow
10
+ */
11
+
12
+ const { init } = require('./installer');
13
+ const { upgrade } = require('./upgrader');
14
+ const { skill } = require('./skill-registry');
15
+ const { channel, CHANNELS, getLatestVersion } = require('./release-channel');
16
+ const utils = require('./utils');
17
+
18
+ module.exports = {
19
+ init,
20
+ upgrade,
21
+ skill,
22
+ channel,
23
+
24
+ // Release channel utilities
25
+ CHANNELS,
26
+ getLatestVersion,
27
+
28
+ // Shared utilities
29
+ utils,
30
+
31
+ // Version info
32
+ version: require('../package.json').version
33
+ };
@@ -0,0 +1,467 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Wogi Flow Installer
5
+ *
6
+ * Handles project initialization with `flow init`.
7
+ * Creates the .workflow directory structure, configures CLI bridges,
8
+ * and sets up the project for use with the selected AI CLI.
9
+ *
10
+ * @module lib/installer
11
+ */
12
+
13
+ const fs = require('fs');
14
+ const path = require('path');
15
+ const readline = require('readline');
16
+
17
+ // Shared utilities
18
+ const { copyDir, safeReadJson } = require('./utils');
19
+
20
+ // Package root (where wogi-flow is installed)
21
+ const PACKAGE_ROOT = path.resolve(__dirname, '..');
22
+
23
+ // Supported CLIs
24
+ const SUPPORTED_CLIS = {
25
+ claude: {
26
+ name: 'Claude Code',
27
+ dir: '.claude',
28
+ configFile: 'CLAUDE.md',
29
+ description: 'Anthropic Claude Code CLI'
30
+ },
31
+ gemini: {
32
+ name: 'Gemini CLI',
33
+ dir: '.gemini',
34
+ configFile: 'GEMINI.md',
35
+ description: 'Google Gemini CLI'
36
+ },
37
+ opencode: {
38
+ name: 'OpenCode',
39
+ dir: '.opencode',
40
+ configFile: 'config.yaml',
41
+ description: 'OpenCode CLI'
42
+ }
43
+ };
44
+
45
+ // Default configuration
46
+ const DEFAULT_CONFIG = {
47
+ version: '1.9.0',
48
+ projectName: '',
49
+ cli: 'claude',
50
+ strictMode: true,
51
+ releaseChannel: 'stable'
52
+ };
53
+
54
+ /**
55
+ * Parse command line arguments with bounds checking
56
+ * @param {string[]} args - Command line arguments
57
+ * @returns {Object} Parsed options
58
+ */
59
+ function parseArgs(args) {
60
+ const options = {
61
+ cli: null,
62
+ force: false,
63
+ yes: false,
64
+ help: false
65
+ };
66
+
67
+ for (let i = 0; i < args.length; i++) {
68
+ const arg = args[i];
69
+
70
+ if (arg === '--cli' || arg === '-c') {
71
+ // Bounds check before accessing next argument
72
+ if (i + 1 >= args.length) {
73
+ console.error('Error: --cli requires a value');
74
+ options.help = true;
75
+ break;
76
+ }
77
+ options.cli = args[++i];
78
+ } else if (arg === '--force' || arg === '-f') {
79
+ options.force = true;
80
+ } else if (arg === '--yes' || arg === '-y') {
81
+ options.yes = true;
82
+ } else if (arg === '--help' || arg === '-h') {
83
+ options.help = true;
84
+ }
85
+ }
86
+
87
+ return options;
88
+ }
89
+
90
+ /**
91
+ * Show help message
92
+ */
93
+ function showHelp() {
94
+ console.log(`
95
+ Usage: flow init [options]
96
+
97
+ Initialize Wogi Flow in the current directory.
98
+
99
+ Options:
100
+ --cli, -c <name> Select CLI (claude, gemini, opencode)
101
+ --force, -f Overwrite existing configuration
102
+ --yes, -y Accept all defaults without prompting
103
+ --help, -h Show this help message
104
+
105
+ Examples:
106
+ flow init # Interactive setup
107
+ flow init --cli claude # Initialize with Claude Code
108
+ flow init --cli claude -y # Quick setup with defaults
109
+ flow init --force # Reinitialize existing project
110
+ `);
111
+ }
112
+
113
+ /**
114
+ * Create readline interface for user input
115
+ * @returns {readline.Interface}
116
+ */
117
+ function createReadline() {
118
+ return readline.createInterface({
119
+ input: process.stdin,
120
+ output: process.stdout
121
+ });
122
+ }
123
+
124
+ /**
125
+ * Ask a question and get user input
126
+ * @param {readline.Interface} rl - Readline interface
127
+ * @param {string} question - Question to ask
128
+ * @param {string} defaultValue - Default value
129
+ * @returns {Promise<string>} User's answer
130
+ */
131
+ function ask(rl, question, defaultValue = '') {
132
+ const prompt = defaultValue ? `${question} [${defaultValue}]: ` : `${question}: `;
133
+ return new Promise((resolve) => {
134
+ rl.question(prompt, (answer) => {
135
+ resolve(answer.trim() || defaultValue);
136
+ });
137
+ });
138
+ }
139
+
140
+ /**
141
+ * Ask a yes/no question
142
+ * @param {readline.Interface} rl - Readline interface
143
+ * @param {string} question - Question to ask
144
+ * @param {boolean} defaultValue - Default value
145
+ * @returns {Promise<boolean>}
146
+ */
147
+ async function askYesNo(rl, question, defaultValue = true) {
148
+ const hint = defaultValue ? '[Y/n]' : '[y/N]';
149
+ const answer = await ask(rl, `${question} ${hint}`, '');
150
+ if (!answer) return defaultValue;
151
+ return answer.toLowerCase().startsWith('y');
152
+ }
153
+
154
+ /**
155
+ * Select from a list of options
156
+ * @param {readline.Interface} rl - Readline interface
157
+ * @param {string} question - Question to ask
158
+ * @param {Object} options - Options object {key: {name, description}}
159
+ * @param {string} defaultKey - Default selection
160
+ * @returns {Promise<string>} Selected key
161
+ */
162
+ async function selectOption(rl, question, options, defaultKey) {
163
+ console.log(`\n${question}`);
164
+ const keys = Object.keys(options);
165
+ keys.forEach((key, index) => {
166
+ const opt = options[key];
167
+ const marker = key === defaultKey ? '>' : ' ';
168
+ console.log(` ${marker} ${index + 1}. ${opt.name} - ${opt.description}`);
169
+ });
170
+
171
+ const answer = await ask(rl, 'Enter number or name', defaultKey);
172
+
173
+ // Check if answer is a number
174
+ const num = parseInt(answer, 10);
175
+ if (!isNaN(num) && num >= 1 && num <= keys.length) {
176
+ return keys[num - 1];
177
+ }
178
+
179
+ // Check if answer matches a key
180
+ if (options[answer.toLowerCase()]) {
181
+ return answer.toLowerCase();
182
+ }
183
+
184
+ return defaultKey;
185
+ }
186
+
187
+ // copyDir is imported from ./utils
188
+
189
+ /**
190
+ * Create the .workflow directory structure
191
+ * @param {string} projectRoot - Project root directory
192
+ * @param {Object} config - Configuration options
193
+ */
194
+ function createWorkflowStructure(projectRoot, config) {
195
+ const workflowDir = path.join(projectRoot, '.workflow');
196
+
197
+ // Create main directories
198
+ const dirs = [
199
+ 'state',
200
+ 'changes/general',
201
+ 'models',
202
+ 'templates',
203
+ 'agents',
204
+ 'bridges',
205
+ 'roadmap',
206
+ 'specs',
207
+ 'verifications'
208
+ ];
209
+
210
+ for (const dir of dirs) {
211
+ fs.mkdirSync(path.join(workflowDir, dir), { recursive: true });
212
+ }
213
+
214
+ // Create config.json
215
+ const configPath = path.join(workflowDir, 'config.json');
216
+ const configContent = {
217
+ version: config.version,
218
+ projectName: config.projectName,
219
+ cli: config.cli,
220
+ enforcement: {
221
+ strictMode: config.strictMode,
222
+ requireTasks: true,
223
+ requireApproval: true
224
+ },
225
+ releaseChannel: config.releaseChannel,
226
+ autoUpdate: {
227
+ enabled: true,
228
+ notifyOnly: true
229
+ }
230
+ };
231
+ fs.writeFileSync(configPath, JSON.stringify(configContent, null, 2));
232
+
233
+ // Create ready.json
234
+ const readyPath = path.join(workflowDir, 'state', 'ready.json');
235
+ const readyContent = {
236
+ lastUpdated: new Date().toISOString(),
237
+ ready: [],
238
+ inProgress: [],
239
+ blocked: [],
240
+ recentlyCompleted: []
241
+ };
242
+ fs.writeFileSync(readyPath, JSON.stringify(readyContent, null, 2));
243
+
244
+ // Create empty state files
245
+ const stateFiles = [
246
+ { name: 'request-log.md', content: '# Request Log\n\nAutomatic log of all requests that changed files.\n\n---\n' },
247
+ { name: 'decisions.md', content: '# Project Decisions\n\nKey decisions and patterns for this project.\n\n---\n' },
248
+ { name: 'app-map.md', content: '# Application Map\n\nComponent registry for this project.\n\n---\n' },
249
+ { name: 'progress.md', content: '# Progress Notes\n\nSession handoff notes.\n\n---\n' }
250
+ ];
251
+
252
+ for (const file of stateFiles) {
253
+ const filePath = path.join(workflowDir, 'state', file.name);
254
+ if (!fs.existsSync(filePath)) {
255
+ fs.writeFileSync(filePath, file.content);
256
+ }
257
+ }
258
+
259
+ // Create model registry
260
+ const registryPath = path.join(workflowDir, 'models', 'registry.json');
261
+ const registryContent = {
262
+ version: '1.0',
263
+ lastUpdated: new Date().toISOString(),
264
+ models: {}
265
+ };
266
+ fs.writeFileSync(registryPath, JSON.stringify(registryContent, null, 2));
267
+
268
+ // Copy templates from package
269
+ const packageTemplates = path.join(PACKAGE_ROOT, '.workflow', 'templates');
270
+ const projectTemplates = path.join(workflowDir, 'templates');
271
+ if (fs.existsSync(packageTemplates)) {
272
+ copyDir(packageTemplates, projectTemplates);
273
+ }
274
+
275
+ // Copy agents from package
276
+ const packageAgents = path.join(PACKAGE_ROOT, '.workflow', 'agents');
277
+ const projectAgents = path.join(workflowDir, 'agents');
278
+ if (fs.existsSync(packageAgents)) {
279
+ copyDir(packageAgents, projectAgents);
280
+ }
281
+
282
+ // Copy bridges from package
283
+ const packageBridges = path.join(PACKAGE_ROOT, '.workflow', 'bridges');
284
+ const projectBridges = path.join(workflowDir, 'bridges');
285
+ if (fs.existsSync(packageBridges)) {
286
+ copyDir(packageBridges, projectBridges);
287
+ }
288
+
289
+ console.log(' Created .workflow/ directory structure');
290
+ }
291
+
292
+ /**
293
+ * Create CLI-specific configuration
294
+ * @param {string} projectRoot - Project root directory
295
+ * @param {string} cliKey - CLI identifier
296
+ * @param {Object} config - Configuration
297
+ */
298
+ function createCLIConfig(projectRoot, cliKey, config) {
299
+ const cli = SUPPORTED_CLIS[cliKey];
300
+ if (!cli) {
301
+ console.error(`Unknown CLI: ${cliKey}`);
302
+ return;
303
+ }
304
+
305
+ const cliDir = path.join(projectRoot, cli.dir);
306
+ fs.mkdirSync(cliDir, { recursive: true });
307
+
308
+ // Create CLI-specific config file
309
+ if (cliKey === 'claude') {
310
+ const claudeMd = `# Project Instructions
311
+
312
+ You are an AI development assistant using the Wogi Flow methodology.
313
+
314
+ ## Quick Start
315
+
316
+ \`\`\`bash
317
+ cat .workflow/config.json # Read config
318
+ cat .workflow/state/ready.json # Check tasks
319
+ \`\`\`
320
+
321
+ ## Core Commands
322
+
323
+ - \`/wogi-ready\` - Show available tasks
324
+ - \`/wogi-start TASK-X\` - Start a task
325
+ - \`/wogi-status\` - Project overview
326
+
327
+ Generated by Wogi Flow v${config.version}
328
+ `;
329
+ fs.writeFileSync(path.join(cliDir, 'CLAUDE.md'), claudeMd);
330
+
331
+ // Create skills directory
332
+ fs.mkdirSync(path.join(cliDir, 'skills'), { recursive: true });
333
+
334
+ // Create docs directory
335
+ fs.mkdirSync(path.join(cliDir, 'docs'), { recursive: true });
336
+
337
+ // Create rules directory
338
+ fs.mkdirSync(path.join(cliDir, 'rules'), { recursive: true });
339
+ }
340
+
341
+ console.log(` Created ${cli.dir}/ for ${cli.name}`);
342
+ }
343
+
344
+ /**
345
+ * Copy scripts from package to project
346
+ * @param {string} projectRoot - Project root directory
347
+ */
348
+ function copyScripts(projectRoot) {
349
+ const packageScripts = path.join(PACKAGE_ROOT, 'scripts');
350
+ const projectScripts = path.join(projectRoot, 'scripts');
351
+
352
+ if (fs.existsSync(packageScripts)) {
353
+ copyDir(packageScripts, projectScripts);
354
+
355
+ // Make flow script executable
356
+ const flowScript = path.join(projectScripts, 'flow');
357
+ if (fs.existsSync(flowScript)) {
358
+ fs.chmodSync(flowScript, '755');
359
+ }
360
+
361
+ console.log(' Copied scripts/ directory');
362
+ }
363
+ }
364
+
365
+ /**
366
+ * Main initialization function
367
+ * @param {string[]} args - Command line arguments
368
+ */
369
+ async function init(args) {
370
+ const options = parseArgs(args);
371
+
372
+ if (options.help) {
373
+ showHelp();
374
+ return;
375
+ }
376
+
377
+ const projectRoot = process.cwd();
378
+ const workflowDir = path.join(projectRoot, '.workflow');
379
+
380
+ // Check for existing installation
381
+ if (fs.existsSync(workflowDir) && !options.force) {
382
+ console.log('Wogi Flow is already initialized in this directory.');
383
+ console.log('Use --force to reinitialize.');
384
+ return;
385
+ }
386
+
387
+ console.log('\n🚀 Wogi Flow Installer\n');
388
+
389
+ let config = { ...DEFAULT_CONFIG };
390
+
391
+ // Detect project name from package.json or directory name
392
+ const packageJsonPath = path.join(projectRoot, 'package.json');
393
+ const pkg = safeReadJson(packageJsonPath);
394
+ if (pkg && pkg.name) {
395
+ config.projectName = pkg.name;
396
+ } else {
397
+ config.projectName = path.basename(projectRoot);
398
+ }
399
+
400
+ // Interactive or quick mode
401
+ if (options.yes) {
402
+ // Use defaults and CLI option if provided
403
+ config.cli = options.cli || 'claude';
404
+ console.log(`Using quick mode with ${SUPPORTED_CLIS[config.cli].name}`);
405
+ } else {
406
+ // Interactive mode
407
+ const rl = createReadline();
408
+
409
+ try {
410
+ // Confirm project name
411
+ config.projectName = await ask(rl, 'Project name', config.projectName);
412
+
413
+ // Select CLI
414
+ config.cli = options.cli || await selectOption(
415
+ rl,
416
+ 'Which AI CLI are you using?',
417
+ SUPPORTED_CLIS,
418
+ 'claude'
419
+ );
420
+
421
+ // Enable strict mode?
422
+ config.strictMode = await askYesNo(
423
+ rl,
424
+ 'Enable strict mode (require tasks for changes)?',
425
+ true
426
+ );
427
+
428
+ // Confirm
429
+ console.log('\nConfiguration:');
430
+ console.log(` Project: ${config.projectName}`);
431
+ console.log(` CLI: ${SUPPORTED_CLIS[config.cli].name}`);
432
+ console.log(` Strict Mode: ${config.strictMode ? 'Yes' : 'No'}`);
433
+
434
+ const proceed = await askYesNo(rl, '\nProceed with installation?', true);
435
+ if (!proceed) {
436
+ console.log('Installation cancelled.');
437
+ rl.close();
438
+ return;
439
+ }
440
+
441
+ rl.close();
442
+ } catch (err) {
443
+ rl.close();
444
+ throw err;
445
+ }
446
+ }
447
+
448
+ console.log('\nInstalling Wogi Flow...\n');
449
+
450
+ // Create structure
451
+ createWorkflowStructure(projectRoot, config);
452
+
453
+ // Create CLI config
454
+ createCLIConfig(projectRoot, config.cli, config);
455
+
456
+ // Copy scripts
457
+ copyScripts(projectRoot);
458
+
459
+ console.log('\n✅ Wogi Flow initialized successfully!\n');
460
+ console.log('Next steps:');
461
+ console.log(' 1. Review .workflow/config.json');
462
+ console.log(' 2. Run `./scripts/flow status` to see project status');
463
+ console.log(' 3. Create your first task with `./scripts/flow story "Task title"`');
464
+ console.log('');
465
+ }
466
+
467
+ module.exports = { init };