moflo 4.8.10 → 4.8.12

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 (182) hide show
  1. package/.claude/agents/browser/browser-agent.yaml +182 -0
  2. package/.claude/agents/core/coder.md +265 -265
  3. package/.claude/agents/core/planner.md +167 -167
  4. package/.claude/agents/core/researcher.md +189 -189
  5. package/.claude/agents/core/reviewer.md +325 -325
  6. package/.claude/agents/core/tester.md +318 -318
  7. package/.claude/agents/dual-mode/codex-coordinator.md +224 -224
  8. package/.claude/agents/dual-mode/codex-worker.md +211 -211
  9. package/.claude/agents/dual-mode/dual-orchestrator.md +291 -291
  10. package/.claude/agents/github/code-review-swarm.md +537 -537
  11. package/.claude/agents/github/github-modes.md +172 -172
  12. package/.claude/agents/github/issue-tracker.md +318 -318
  13. package/.claude/agents/github/multi-repo-swarm.md +552 -552
  14. package/.claude/agents/github/pr-manager.md +190 -190
  15. package/.claude/agents/github/project-board-sync.md +508 -508
  16. package/.claude/agents/github/release-manager.md +366 -366
  17. package/.claude/agents/github/release-swarm.md +582 -582
  18. package/.claude/agents/github/repo-architect.md +397 -397
  19. package/.claude/agents/github/swarm-issue.md +572 -572
  20. package/.claude/agents/github/swarm-pr.md +427 -427
  21. package/.claude/agents/github/sync-coordinator.md +451 -451
  22. package/.claude/agents/github/workflow-automation.md +634 -634
  23. package/.claude/agents/goal/code-goal-planner.md +445 -445
  24. package/.claude/agents/hive-mind/collective-intelligence-coordinator.md +129 -129
  25. package/.claude/agents/hive-mind/queen-coordinator.md +202 -202
  26. package/.claude/agents/hive-mind/scout-explorer.md +241 -241
  27. package/.claude/agents/hive-mind/swarm-memory-manager.md +192 -192
  28. package/.claude/agents/hive-mind/worker-specialist.md +216 -216
  29. package/.claude/agents/neural/safla-neural.md +73 -73
  30. package/.claude/agents/reasoning/goal-planner.md +72 -72
  31. package/.claude/agents/swarm/adaptive-coordinator.md +395 -395
  32. package/.claude/agents/swarm/hierarchical-coordinator.md +326 -326
  33. package/.claude/agents/swarm/mesh-coordinator.md +391 -391
  34. package/.claude/agents/templates/migration-plan.md +745 -745
  35. package/.claude/commands/agents/agent-spawning.md +28 -28
  36. package/.claude/commands/analysis/COMMAND_COMPLIANCE_REPORT.md +53 -53
  37. package/.claude/commands/analysis/bottleneck-detect.md +162 -162
  38. package/.claude/commands/analysis/performance-bottlenecks.md +58 -58
  39. package/.claude/commands/analysis/token-efficiency.md +44 -44
  40. package/.claude/commands/automation/auto-agent.md +122 -122
  41. package/.claude/commands/automation/self-healing.md +105 -105
  42. package/.claude/commands/automation/session-memory.md +89 -89
  43. package/.claude/commands/automation/smart-agents.md +72 -72
  44. package/.claude/commands/coordination/init.md +44 -44
  45. package/.claude/commands/coordination/orchestrate.md +43 -43
  46. package/.claude/commands/coordination/spawn.md +45 -45
  47. package/.claude/commands/coordination/swarm-init.md +85 -85
  48. package/.claude/commands/github/github-modes.md +146 -146
  49. package/.claude/commands/github/github-swarm.md +121 -121
  50. package/.claude/commands/github/issue-tracker.md +291 -291
  51. package/.claude/commands/github/pr-manager.md +169 -169
  52. package/.claude/commands/github/release-manager.md +337 -337
  53. package/.claude/commands/github/repo-architect.md +366 -366
  54. package/.claude/commands/github/sync-coordinator.md +300 -300
  55. package/.claude/commands/memory/neural.md +47 -47
  56. package/.claude/commands/monitoring/agents.md +44 -44
  57. package/.claude/commands/monitoring/status.md +46 -46
  58. package/.claude/commands/optimization/auto-topology.md +61 -61
  59. package/.claude/commands/optimization/parallel-execution.md +49 -49
  60. package/.claude/commands/sparc/analyzer.md +51 -51
  61. package/.claude/commands/sparc/architect.md +53 -53
  62. package/.claude/commands/sparc/ask.md +97 -97
  63. package/.claude/commands/sparc/batch-executor.md +54 -54
  64. package/.claude/commands/sparc/code.md +89 -89
  65. package/.claude/commands/sparc/coder.md +54 -54
  66. package/.claude/commands/sparc/debug.md +83 -83
  67. package/.claude/commands/sparc/debugger.md +54 -54
  68. package/.claude/commands/sparc/designer.md +53 -53
  69. package/.claude/commands/sparc/devops.md +109 -109
  70. package/.claude/commands/sparc/docs-writer.md +80 -80
  71. package/.claude/commands/sparc/documenter.md +54 -54
  72. package/.claude/commands/sparc/innovator.md +54 -54
  73. package/.claude/commands/sparc/integration.md +83 -83
  74. package/.claude/commands/sparc/mcp.md +117 -117
  75. package/.claude/commands/sparc/memory-manager.md +54 -54
  76. package/.claude/commands/sparc/optimizer.md +54 -54
  77. package/.claude/commands/sparc/orchestrator.md +131 -131
  78. package/.claude/commands/sparc/post-deployment-monitoring-mode.md +83 -83
  79. package/.claude/commands/sparc/refinement-optimization-mode.md +83 -83
  80. package/.claude/commands/sparc/researcher.md +54 -54
  81. package/.claude/commands/sparc/reviewer.md +54 -54
  82. package/.claude/commands/sparc/security-review.md +80 -80
  83. package/.claude/commands/sparc/sparc-modes.md +174 -174
  84. package/.claude/commands/sparc/sparc.md +111 -111
  85. package/.claude/commands/sparc/spec-pseudocode.md +80 -80
  86. package/.claude/commands/sparc/supabase-admin.md +348 -348
  87. package/.claude/commands/sparc/swarm-coordinator.md +54 -54
  88. package/.claude/commands/sparc/tdd.md +54 -54
  89. package/.claude/commands/sparc/tester.md +54 -54
  90. package/.claude/commands/sparc/tutorial.md +79 -79
  91. package/.claude/commands/sparc/workflow-manager.md +54 -54
  92. package/.claude/commands/sparc.md +166 -166
  93. package/.claude/commands/swarm/analysis.md +95 -95
  94. package/.claude/commands/swarm/development.md +96 -96
  95. package/.claude/commands/swarm/examples.md +168 -168
  96. package/.claude/commands/swarm/maintenance.md +102 -102
  97. package/.claude/commands/swarm/optimization.md +117 -117
  98. package/.claude/commands/swarm/research.md +136 -136
  99. package/.claude/commands/swarm/testing.md +131 -131
  100. package/.claude/commands/training/neural-patterns.md +73 -73
  101. package/.claude/commands/training/specialization.md +62 -62
  102. package/.claude/commands/workflows/development.md +77 -77
  103. package/.claude/commands/workflows/research.md +62 -62
  104. package/.claude/guidance/moflo-bootstrap.md +129 -0
  105. package/.claude/guidance/{agent-bootstrap.md → shipped/agent-bootstrap.md} +126 -126
  106. package/.claude/guidance/{guidance-memory-strategy.md → shipped/guidance-memory-strategy.md} +262 -262
  107. package/.claude/guidance/{memory-strategy.md → shipped/memory-strategy.md} +204 -204
  108. package/.claude/guidance/{moflo.md → shipped/moflo.md} +45 -31
  109. package/.claude/guidance/{task-swarm-integration.md → shipped/task-swarm-integration.md} +441 -348
  110. package/.claude/helpers/gate-hook.mjs +50 -0
  111. package/.claude/helpers/gate.cjs +138 -236
  112. package/.claude/helpers/hook-handler.cjs +64 -326
  113. package/.claude/helpers/post-commit +16 -0
  114. package/.claude/helpers/pre-commit +26 -0
  115. package/.claude/helpers/prompt-hook.mjs +72 -0
  116. package/.claude/scripts/build-embeddings.mjs +549 -0
  117. package/.claude/scripts/generate-code-map.mjs +697 -0
  118. package/.claude/scripts/hooks.mjs +656 -0
  119. package/.claude/scripts/index-guidance.mjs +893 -0
  120. package/.claude/scripts/index-tests.mjs +710 -0
  121. package/.claude/scripts/semantic-search.mjs +473 -0
  122. package/.claude/scripts/session-start-launcher.mjs +226 -0
  123. package/.claude/settings.json +351 -290
  124. package/.claude/settings.local.json +4 -3
  125. package/.claude/skills/browser/SKILL.md +204 -0
  126. package/.claude/skills/fl/SKILL.md +29 -23
  127. package/.claude/skills/flo/SKILL.md +29 -23
  128. package/.claude/skills/github-code-review/SKILL.md +4 -4
  129. package/.claude/skills/github-multi-repo/SKILL.md +8 -8
  130. package/.claude/skills/github-project-management/SKILL.md +6 -6
  131. package/.claude/skills/github-release-management/SKILL.md +12 -12
  132. package/.claude/skills/github-workflow-automation/SKILL.md +6 -6
  133. package/.claude/skills/hooks-automation/SKILL.md +1201 -1201
  134. package/.claude/skills/performance-analysis/SKILL.md +563 -563
  135. package/.claude/skills/sparc-methodology/SKILL.md +64 -64
  136. package/.claude/skills/swarm-advanced/SKILL.md +77 -77
  137. package/.claude/workflow-state.json +9 -0
  138. package/.claude-plugin/README.md +3 -3
  139. package/.claude-plugin/docs/PLUGIN_SUMMARY.md +3 -3
  140. package/.claude-plugin/docs/QUICKSTART.md +4 -4
  141. package/.claude-plugin/marketplace.json +3 -3
  142. package/.claude-plugin/plugin.json +3 -3
  143. package/.claude-plugin/scripts/install.sh +9 -9
  144. package/.claude-plugin/scripts/verify.sh +7 -7
  145. package/README.md +311 -116
  146. package/bin/gate-hook.mjs +50 -0
  147. package/bin/gate.cjs +138 -0
  148. package/bin/hook-handler.cjs +83 -0
  149. package/bin/hooks.mjs +72 -12
  150. package/bin/index-guidance.mjs +29 -35
  151. package/bin/index-tests.mjs +710 -0
  152. package/bin/lib/process-manager.mjs +243 -0
  153. package/bin/lib/registry-cleanup.cjs +41 -0
  154. package/bin/prompt-hook.mjs +72 -0
  155. package/bin/semantic-search.mjs +472 -440
  156. package/bin/session-start-launcher.mjs +81 -31
  157. package/bin/setup-project.mjs +65 -65
  158. package/package.json +4 -2
  159. package/src/@claude-flow/cli/README.md +1 -1
  160. package/src/@claude-flow/cli/bin/cli.js +175 -175
  161. package/src/@claude-flow/cli/dist/src/commands/doctor.js +1091 -736
  162. package/src/@claude-flow/cli/dist/src/commands/github.d.ts +12 -0
  163. package/src/@claude-flow/cli/dist/src/commands/github.js +505 -0
  164. package/src/@claude-flow/cli/dist/src/commands/hive-mind.js +90 -90
  165. package/src/@claude-flow/cli/dist/src/commands/index.d.ts +1 -0
  166. package/src/@claude-flow/cli/dist/src/commands/index.js +7 -0
  167. package/src/@claude-flow/cli/dist/src/config-adapter.js +1 -1
  168. package/src/@claude-flow/cli/dist/src/init/claudemd-generator.d.ts +29 -24
  169. package/src/@claude-flow/cli/dist/src/init/claudemd-generator.js +73 -494
  170. package/src/@claude-flow/cli/dist/src/init/executor.js +109 -5
  171. package/src/@claude-flow/cli/dist/src/init/helpers-generator.d.ts +14 -0
  172. package/src/@claude-flow/cli/dist/src/init/helpers-generator.js +156 -24
  173. package/src/@claude-flow/cli/dist/src/init/mcp-generator.js +20 -20
  174. package/src/@claude-flow/cli/dist/src/init/moflo-init.d.ts +30 -23
  175. package/src/@claude-flow/cli/dist/src/init/moflo-init.js +727 -670
  176. package/src/@claude-flow/cli/dist/src/init/settings-generator.js +23 -14
  177. package/src/@claude-flow/cli/dist/src/mcp-server.js +3 -3
  178. package/src/@claude-flow/cli/dist/src/plugins/manager.js +9 -8
  179. package/src/@claude-flow/cli/dist/src/services/worker-daemon.d.ts +1 -0
  180. package/src/@claude-flow/cli/dist/src/services/worker-daemon.js +3 -1
  181. package/src/@claude-flow/cli/dist/src/services/workflow-gate.js +10 -10
  182. package/src/@claude-flow/cli/package.json +106 -106
@@ -0,0 +1,12 @@
1
+ /**
2
+ * V3 CLI GitHub Command
3
+ * Repository setup: CI/CD pipeline generation, branch protection, repo settings.
4
+ *
5
+ * Uses `gh` CLI for GitHub API calls and project detection from moflo.yaml.
6
+ *
7
+ * Created with motailz.com
8
+ */
9
+ import type { Command } from '../types.js';
10
+ export declare const githubCommand: Command;
11
+ export default githubCommand;
12
+ //# sourceMappingURL=github.d.ts.map
@@ -0,0 +1,505 @@
1
+ /**
2
+ * V3 CLI GitHub Command
3
+ * Repository setup: CI/CD pipeline generation, branch protection, repo settings.
4
+ *
5
+ * Uses `gh` CLI for GitHub API calls and project detection from moflo.yaml.
6
+ *
7
+ * Created with motailz.com
8
+ */
9
+ import { output } from '../output.js';
10
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
11
+ import { join } from 'path';
12
+ import { execSync } from 'child_process';
13
+ // ============================================================================
14
+ // Helpers
15
+ // ============================================================================
16
+ function runGh(args, cwd, timeout = 15000, stdin) {
17
+ return execSync(`gh ${args}`, {
18
+ encoding: 'utf8',
19
+ cwd,
20
+ timeout,
21
+ windowsHide: true,
22
+ input: stdin,
23
+ stdio: stdin ? ['pipe', 'pipe', 'pipe'] : ['pipe', 'pipe', 'pipe'],
24
+ }).trim();
25
+ }
26
+ function ghAvailable() {
27
+ try {
28
+ execSync('gh --version', { encoding: 'utf8', timeout: 5000, windowsHide: true, stdio: 'pipe' });
29
+ return true;
30
+ }
31
+ catch {
32
+ return false;
33
+ }
34
+ }
35
+ function ghAuthenticated() {
36
+ try {
37
+ execSync('gh auth status', { encoding: 'utf8', timeout: 5000, windowsHide: true, stdio: 'pipe' });
38
+ return true;
39
+ }
40
+ catch {
41
+ return false;
42
+ }
43
+ }
44
+ /** Read moflo.yaml and extract project info for CI generation */
45
+ function readProjectConfig(cwd) {
46
+ const defaults = {
47
+ name: '',
48
+ extensions: ['.ts', '.js'],
49
+ testDirs: ['tests'],
50
+ srcDirs: ['src'],
51
+ hasTypeScript: false,
52
+ hasTests: false,
53
+ packageManager: 'npm',
54
+ };
55
+ // Detect project name from package.json
56
+ const pkgPath = join(cwd, 'package.json');
57
+ if (existsSync(pkgPath)) {
58
+ try {
59
+ const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'));
60
+ defaults.name = pkg.name || '';
61
+ }
62
+ catch { /* ignore */ }
63
+ }
64
+ // Detect package manager
65
+ if (existsSync(join(cwd, 'bun.lockb')) || existsSync(join(cwd, 'bun.lock')))
66
+ defaults.packageManager = 'bun';
67
+ else if (existsSync(join(cwd, 'pnpm-lock.yaml')))
68
+ defaults.packageManager = 'pnpm';
69
+ else if (existsSync(join(cwd, 'yarn.lock')))
70
+ defaults.packageManager = 'yarn';
71
+ // Detect TypeScript
72
+ defaults.hasTypeScript = existsSync(join(cwd, 'tsconfig.json'));
73
+ // Read moflo.yaml for detected dirs/extensions
74
+ const yamlPath = join(cwd, 'moflo.yaml');
75
+ if (existsSync(yamlPath)) {
76
+ try {
77
+ const content = readFileSync(yamlPath, 'utf8');
78
+ // Parse extensions
79
+ const extMatch = content.match(/extensions:\s*\[([^\]]+)\]/);
80
+ if (extMatch) {
81
+ defaults.extensions = extMatch[1].split(',').map(e => e.trim().replace(/"/g, ''));
82
+ }
83
+ // Parse test directories
84
+ const testsBlock = content.match(/tests:\s*\n\s+directories:\s*\n((?:\s+-\s+.+\n?)+)/);
85
+ if (testsBlock) {
86
+ const items = testsBlock[1].match(/-\s+(.+)/g);
87
+ if (items)
88
+ defaults.testDirs = items.map(i => i.replace(/^-\s+/, '').trim());
89
+ }
90
+ // Parse source directories
91
+ const codeBlock = content.match(/code_map:\s*\n\s+directories:\s*\n((?:\s+-\s+.+\n?)+)/);
92
+ if (codeBlock) {
93
+ const items = codeBlock[1].match(/-\s+(.+)/g);
94
+ if (items)
95
+ defaults.srcDirs = items.map(i => i.replace(/^-\s+/, '').trim());
96
+ }
97
+ }
98
+ catch { /* ignore parse errors */ }
99
+ }
100
+ // Check if test dirs actually exist
101
+ defaults.hasTests = defaults.testDirs.some(d => existsSync(join(cwd, d)));
102
+ return defaults;
103
+ }
104
+ /** Get the default branch name for the current repo */
105
+ function getDefaultBranch(cwd) {
106
+ try {
107
+ return runGh('repo view --json defaultBranchRef --jq .defaultBranchRef.name', cwd);
108
+ }
109
+ catch {
110
+ // Fallback: check local git
111
+ try {
112
+ return execSync('git symbolic-ref refs/remotes/origin/HEAD', {
113
+ encoding: 'utf8', cwd, timeout: 5000, windowsHide: true, stdio: 'pipe',
114
+ }).trim().replace('refs/remotes/origin/', '');
115
+ }
116
+ catch {
117
+ return 'main';
118
+ }
119
+ }
120
+ }
121
+ /** Get the repo owner/name from gh */
122
+ function getRepoSlug(cwd) {
123
+ try {
124
+ return runGh('repo view --json nameWithOwner --jq .nameWithOwner', cwd);
125
+ }
126
+ catch {
127
+ return null;
128
+ }
129
+ }
130
+ // ============================================================================
131
+ // CI Workflow Generation
132
+ // ============================================================================
133
+ function generateCIWorkflow(config, defaultBranch) {
134
+ const pm = config.packageManager;
135
+ const install = pm === 'pnpm' ? 'pnpm install --frozen-lockfile'
136
+ : pm === 'yarn' ? 'yarn install --frozen-lockfile'
137
+ : pm === 'bun' ? 'bun install --frozen-lockfile'
138
+ : 'npm ci';
139
+ const run = pm === 'pnpm' ? 'pnpm' : pm === 'yarn' ? 'yarn' : pm === 'bun' ? 'bun run' : 'npm run';
140
+ const setupPm = pm === 'pnpm' ? `
141
+ - name: Install pnpm
142
+ uses: pnpm/action-setup@v4
143
+ with:
144
+ version: latest
145
+ ` : '';
146
+ const nodeCache = pm === 'pnpm' ? 'pnpm' : pm === 'yarn' ? 'yarn' : pm === 'bun' ? '' : 'npm';
147
+ const setupNode = nodeCache ? `
148
+ - name: Setup Node.js
149
+ uses: actions/setup-node@v4
150
+ with:
151
+ node-version: 20
152
+ cache: '${nodeCache}'
153
+ ` : `
154
+ - name: Setup Node.js
155
+ uses: actions/setup-node@v4
156
+ with:
157
+ node-version: 20
158
+ `;
159
+ const setupBun = pm === 'bun' ? `
160
+ - name: Setup Bun
161
+ uses: oven-sh/setup-bun@v2
162
+ ` : '';
163
+ const lintStep = `
164
+ - name: Lint
165
+ run: ${run} lint --max-warnings 0
166
+ continue-on-error: true`;
167
+ const typeCheckStep = config.hasTypeScript ? `
168
+
169
+ - name: Type check
170
+ run: ${run} typecheck` : '';
171
+ const testStep = config.hasTests ? `
172
+
173
+ - name: Test
174
+ run: ${run} test` : '';
175
+ return `# CI pipeline — generated by moflo (https://github.com/eric-cielo/moflo)
176
+ # Runs on every push to ${defaultBranch} and on all pull requests.
177
+
178
+ name: CI
179
+
180
+ on:
181
+ push:
182
+ branches: [${defaultBranch}]
183
+ pull_request:
184
+ branches: [${defaultBranch}]
185
+
186
+ concurrency:
187
+ group: \${{ github.workflow }}-\${{ github.ref }}
188
+ cancel-in-progress: true
189
+
190
+ permissions:
191
+ contents: read
192
+
193
+ jobs:
194
+ build:
195
+ runs-on: ubuntu-latest
196
+ timeout-minutes: 15
197
+
198
+ steps:
199
+ - name: Checkout
200
+ uses: actions/checkout@v4
201
+ ${setupPm}${setupNode}${setupBun}
202
+ - name: Install dependencies
203
+ run: ${install}
204
+
205
+ - name: Build
206
+ run: ${run} build
207
+ ${lintStep}${typeCheckStep}${testStep}
208
+ `;
209
+ }
210
+ // ============================================================================
211
+ // Subcommands
212
+ // ============================================================================
213
+ const ciCommand = {
214
+ name: 'ci',
215
+ description: 'Generate a GitHub Actions CI workflow based on your project',
216
+ options: [
217
+ { name: 'force', short: 'f', type: 'boolean', description: 'Overwrite existing workflow', default: false },
218
+ { name: 'dry-run', short: 'd', type: 'boolean', description: 'Print workflow to stdout instead of writing', default: false },
219
+ ],
220
+ examples: [
221
+ { command: 'flo github ci', description: 'Generate .github/workflows/ci.yml' },
222
+ { command: 'flo github ci --dry-run', description: 'Preview without writing' },
223
+ ],
224
+ action: async (ctx) => {
225
+ const force = ctx.flags.force;
226
+ const dryRun = (ctx.flags['dry-run'] || ctx.flags.dryRun);
227
+ const cwd = ctx.cwd;
228
+ const config = readProjectConfig(cwd);
229
+ const defaultBranch = getDefaultBranch(cwd);
230
+ const workflow = generateCIWorkflow(config, defaultBranch);
231
+ if (dryRun) {
232
+ output.writeln(workflow);
233
+ return { success: true };
234
+ }
235
+ const workflowPath = join(cwd, '.github', 'workflows', 'ci.yml');
236
+ if (existsSync(workflowPath) && !force) {
237
+ output.printWarning('.github/workflows/ci.yml already exists (use --force to overwrite)');
238
+ return { success: false, exitCode: 1 };
239
+ }
240
+ mkdirSync(join(cwd, '.github', 'workflows'), { recursive: true });
241
+ writeFileSync(workflowPath, workflow, 'utf8');
242
+ output.writeln();
243
+ output.writeln(output.bold('CI Workflow Generated'));
244
+ output.writeln();
245
+ output.writeln(` ${output.success('✓')} .github/workflows/ci.yml`);
246
+ output.writeln();
247
+ output.writeln(output.dim(` Package manager: ${config.packageManager}`));
248
+ output.writeln(output.dim(` TypeScript: ${config.hasTypeScript ? 'yes' : 'no'}`));
249
+ output.writeln(output.dim(` Tests: ${config.hasTests ? config.testDirs.join(', ') : 'none detected'}`));
250
+ output.writeln(output.dim(` Default branch: ${defaultBranch}`));
251
+ output.writeln();
252
+ output.printInfo('Review the workflow, then commit and push to activate it.');
253
+ return { success: true };
254
+ },
255
+ };
256
+ const settingsCommand = {
257
+ name: 'settings',
258
+ description: 'Apply recommended repo settings and branch protection via gh CLI',
259
+ options: [
260
+ { name: 'dry-run', short: 'd', type: 'boolean', description: 'Show what would be applied without making changes', default: false },
261
+ { name: 'branch', short: 'b', type: 'string', description: 'Branch to protect (default: repo default branch)' },
262
+ { name: 'skip-protection', type: 'boolean', description: 'Skip branch protection rules', default: false },
263
+ { name: 'skip-repo', type: 'boolean', description: 'Skip repo-level settings', default: false },
264
+ { name: 'required-reviews', type: 'string', description: 'Required approving reviews (0 to disable)', default: '1' },
265
+ { name: 'require-ci', type: 'boolean', description: 'Require CI status checks to pass before merge', default: true },
266
+ ],
267
+ examples: [
268
+ { command: 'flo github settings', description: 'Apply all recommended settings' },
269
+ { command: 'flo github settings --dry-run', description: 'Preview changes' },
270
+ { command: 'flo github settings --required-reviews 2', description: 'Require 2 approving reviews' },
271
+ { command: 'flo github settings --skip-protection', description: 'Only apply repo-level settings' },
272
+ ],
273
+ action: async (ctx) => {
274
+ const dryRun = (ctx.flags['dry-run'] || ctx.flags.dryRun);
275
+ const skipProtection = (ctx.flags['skip-protection'] || ctx.flags.skipProtection);
276
+ const skipRepo = (ctx.flags['skip-repo'] || ctx.flags.skipRepo);
277
+ const requiredReviews = parseInt((ctx.flags['required-reviews'] || ctx.flags.requiredReviews) || '1', 10);
278
+ const requireCi = (ctx.flags['require-ci'] ?? ctx.flags.requireCi ?? true);
279
+ const cwd = ctx.cwd;
280
+ if (!ghAvailable()) {
281
+ output.printError('GitHub CLI (gh) is required but not installed.');
282
+ output.printInfo('Install: https://cli.github.com');
283
+ return { success: false, exitCode: 1 };
284
+ }
285
+ if (!ghAuthenticated()) {
286
+ output.printError('Not authenticated with GitHub CLI.');
287
+ output.printInfo('Run: gh auth login');
288
+ return { success: false, exitCode: 1 };
289
+ }
290
+ const slug = getRepoSlug(cwd);
291
+ if (!slug) {
292
+ output.printError('Could not determine repository. Are you in a git repo linked to GitHub?');
293
+ return { success: false, exitCode: 1 };
294
+ }
295
+ const branch = ctx.flags.branch || getDefaultBranch(cwd);
296
+ output.writeln();
297
+ output.writeln(output.bold('GitHub Repository Settings'));
298
+ output.writeln(output.dim(` Repository: ${slug}`));
299
+ output.writeln(output.dim(` Branch: ${branch}`));
300
+ if (dryRun)
301
+ output.writeln(output.warning(' DRY RUN — no changes will be made'));
302
+ output.writeln();
303
+ const applied = [];
304
+ const errors = [];
305
+ // ── Repo-level settings ──────────────────────────────────────────
306
+ if (!skipRepo) {
307
+ // Group settings into batches — some fields must be set together
308
+ const settingsBatches = [
309
+ {
310
+ payload: {
311
+ delete_branch_on_merge: true,
312
+ allow_squash_merge: true,
313
+ allow_merge_commit: true,
314
+ allow_rebase_merge: true,
315
+ allow_auto_merge: true,
316
+ allow_update_branch: true,
317
+ // Title + message must be set together or message fails
318
+ squash_merge_commit_title: 'PR_TITLE',
319
+ squash_merge_commit_message: 'PR_BODY',
320
+ },
321
+ labels: [
322
+ 'Delete branch on merge',
323
+ 'Allow squash merge',
324
+ 'Allow merge commits',
325
+ 'Allow rebase merge',
326
+ 'Squash defaults: PR title + body',
327
+ 'Allow auto-merge',
328
+ 'Allow update branch button',
329
+ ],
330
+ },
331
+ ];
332
+ for (const batch of settingsBatches) {
333
+ if (dryRun) {
334
+ for (const label of batch.labels) {
335
+ output.writeln(` ${output.dim('○')} ${label}`);
336
+ }
337
+ applied.push(...batch.labels);
338
+ continue;
339
+ }
340
+ try {
341
+ runGh(`api repos/${slug} -X PATCH --input -`, cwd, 15000, JSON.stringify(batch.payload));
342
+ for (const label of batch.labels) {
343
+ output.writeln(` ${output.success('✓')} ${label}`);
344
+ }
345
+ applied.push(...batch.labels);
346
+ }
347
+ catch (e) {
348
+ const msg = e instanceof Error ? e.message : String(e);
349
+ for (const label of batch.labels) {
350
+ output.writeln(` ${output.warning('⚠')} ${label} — ${msg.split('\n')[0]}`);
351
+ }
352
+ errors.push(...batch.labels);
353
+ }
354
+ }
355
+ output.writeln();
356
+ }
357
+ // ── Branch protection ────────────────────────────────────────────
358
+ if (!skipProtection) {
359
+ output.writeln(output.bold(' Branch Protection'));
360
+ output.writeln();
361
+ // Build branch protection payload
362
+ const protection = {
363
+ enforce_admins: false,
364
+ required_pull_request_reviews: requiredReviews > 0 ? {
365
+ required_approving_review_count: requiredReviews,
366
+ dismiss_stale_reviews: true,
367
+ require_code_owner_reviews: false,
368
+ } : null,
369
+ required_status_checks: requireCi ? {
370
+ strict: true,
371
+ contexts: [], // Empty = any passing check counts
372
+ } : null,
373
+ restrictions: null,
374
+ required_linear_history: true,
375
+ allow_force_pushes: false,
376
+ allow_deletions: false,
377
+ };
378
+ const protectionItems = [
379
+ requiredReviews > 0 ? `Require ${requiredReviews} approving review${requiredReviews > 1 ? 's' : ''}` : null,
380
+ requiredReviews > 0 ? 'Dismiss stale reviews on new commits' : null,
381
+ requireCi ? 'Require status checks to pass' : null,
382
+ requireCi ? 'Require branch to be up to date' : null,
383
+ 'Require linear history',
384
+ 'Block force pushes',
385
+ 'Block branch deletion',
386
+ ].filter(Boolean);
387
+ if (dryRun) {
388
+ for (const item of protectionItems) {
389
+ output.writeln(` ${output.dim('○')} ${item}`);
390
+ }
391
+ applied.push(...protectionItems);
392
+ }
393
+ else {
394
+ try {
395
+ const payload = JSON.stringify(protection);
396
+ runGh(`api repos/${slug}/branches/${branch}/protection -X PUT --input -`, cwd, 15000, payload);
397
+ for (const item of protectionItems) {
398
+ output.writeln(` ${output.success('✓')} ${item}`);
399
+ }
400
+ applied.push(...protectionItems);
401
+ }
402
+ catch (e) {
403
+ const msg = e instanceof Error ? e.message : String(e);
404
+ if (msg.includes('not found') || msg.includes('404')) {
405
+ output.writeln(` ${output.warning('⚠')} Branch protection requires GitHub Pro, Team, or Enterprise`);
406
+ }
407
+ else if (msg.includes('403')) {
408
+ output.writeln(` ${output.warning('⚠')} Insufficient permissions — need admin access to set branch protection`);
409
+ }
410
+ else {
411
+ output.writeln(` ${output.error('✗')} Failed to set branch protection: ${msg.split('\n')[0]}`);
412
+ }
413
+ errors.push('Branch protection');
414
+ }
415
+ }
416
+ }
417
+ // ── Summary ──────────────────────────────────────────────────────
418
+ output.writeln();
419
+ output.writeln(output.dim('─'.repeat(50)));
420
+ if (dryRun) {
421
+ output.writeln();
422
+ output.printInfo(`Would apply ${applied.length} settings. Run without --dry-run to apply.`);
423
+ }
424
+ else if (errors.length === 0) {
425
+ output.writeln();
426
+ output.printSuccess(`Applied ${applied.length} settings to ${slug}`);
427
+ }
428
+ else {
429
+ output.writeln();
430
+ output.printWarning(`Applied ${applied.length} settings, ${errors.length} had issues`);
431
+ }
432
+ return { success: errors.length === 0 || dryRun };
433
+ },
434
+ };
435
+ const setupCommand = {
436
+ name: 'setup',
437
+ description: 'One-shot: generate CI workflow + apply repo settings and branch protection',
438
+ options: [
439
+ { name: 'dry-run', short: 'd', type: 'boolean', description: 'Preview all changes without applying', default: false },
440
+ { name: 'force', short: 'f', type: 'boolean', description: 'Overwrite existing CI workflow', default: false },
441
+ { name: 'required-reviews', type: 'string', description: 'Required approving reviews (0 to disable)', default: '1' },
442
+ { name: 'skip-ci', type: 'boolean', description: 'Skip CI workflow generation', default: false },
443
+ { name: 'skip-protection', type: 'boolean', description: 'Skip branch protection rules', default: false },
444
+ { name: 'skip-repo', type: 'boolean', description: 'Skip repo-level settings', default: false },
445
+ ],
446
+ examples: [
447
+ { command: 'flo github setup', description: 'Generate CI + apply all settings' },
448
+ { command: 'flo github setup --dry-run', description: 'Preview everything' },
449
+ { command: 'flo github setup --skip-ci', description: 'Only apply repo settings' },
450
+ ],
451
+ action: async (ctx) => {
452
+ const dryRun = (ctx.flags['dry-run'] || ctx.flags.dryRun);
453
+ const skipCi = (ctx.flags['skip-ci'] || ctx.flags.skipCi);
454
+ output.writeln();
455
+ output.writeln(output.bold('GitHub Project Setup'));
456
+ output.writeln(output.dim('CI workflow + repo settings + branch protection'));
457
+ output.writeln();
458
+ let ciOk = true;
459
+ let settingsOk = true;
460
+ // Step 1: CI workflow
461
+ if (!skipCi) {
462
+ output.writeln(output.bold('Step 1: CI Workflow'));
463
+ output.writeln();
464
+ const ciResult = await ciCommand.action(ctx);
465
+ ciOk = ciResult?.success ?? false;
466
+ output.writeln();
467
+ }
468
+ // Step 2: Repo settings + branch protection
469
+ output.writeln(output.bold(skipCi ? 'Repository Settings' : 'Step 2: Repository Settings'));
470
+ output.writeln();
471
+ const settingsResult = await settingsCommand.action(ctx);
472
+ settingsOk = settingsResult?.success ?? false;
473
+ return { success: ciOk && settingsOk };
474
+ },
475
+ };
476
+ // ============================================================================
477
+ // Main command
478
+ // ============================================================================
479
+ export const githubCommand = {
480
+ name: 'github',
481
+ aliases: ['gh'],
482
+ description: 'GitHub repository setup: CI pipeline, branch protection, repo settings',
483
+ subcommands: [setupCommand, ciCommand, settingsCommand],
484
+ options: [],
485
+ examples: [
486
+ { command: 'flo github setup', description: 'One-shot: CI + settings + branch protection' },
487
+ { command: 'flo github ci', description: 'Generate CI workflow from project config' },
488
+ { command: 'flo github settings', description: 'Apply repo settings and branch protection' },
489
+ { command: 'flo github setup --dry-run', description: 'Preview all changes' },
490
+ ],
491
+ action: async () => {
492
+ output.writeln();
493
+ output.writeln(output.bold('flo github — Repository Setup'));
494
+ output.writeln();
495
+ output.writeln('Subcommands:');
496
+ output.writeln(` ${output.highlight('setup')} One-shot: CI workflow + repo settings + branch protection`);
497
+ output.writeln(` ${output.highlight('ci')} Generate .github/workflows/ci.yml from project config`);
498
+ output.writeln(` ${output.highlight('settings')} Apply repo settings and branch protection via gh CLI`);
499
+ output.writeln();
500
+ output.writeln(output.dim('Run flo github <subcommand> --help for details.'));
501
+ return { success: true };
502
+ },
503
+ };
504
+ export default githubCommand;
505
+ //# sourceMappingURL=github.js.map