moflo 4.8.9 → 4.8.11

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 (166) hide show
  1. package/.claude/agents/core/coder.md +265 -265
  2. package/.claude/agents/core/planner.md +167 -167
  3. package/.claude/agents/core/researcher.md +189 -189
  4. package/.claude/agents/core/reviewer.md +325 -325
  5. package/.claude/agents/core/tester.md +318 -318
  6. package/.claude/agents/dual-mode/codex-coordinator.md +224 -224
  7. package/.claude/agents/dual-mode/codex-worker.md +211 -211
  8. package/.claude/agents/dual-mode/dual-orchestrator.md +291 -291
  9. package/.claude/agents/github/code-review-swarm.md +537 -537
  10. package/.claude/agents/github/github-modes.md +172 -172
  11. package/.claude/agents/github/issue-tracker.md +318 -318
  12. package/.claude/agents/github/multi-repo-swarm.md +552 -552
  13. package/.claude/agents/github/pr-manager.md +190 -190
  14. package/.claude/agents/github/project-board-sync.md +508 -508
  15. package/.claude/agents/github/release-manager.md +366 -366
  16. package/.claude/agents/github/release-swarm.md +582 -582
  17. package/.claude/agents/github/repo-architect.md +397 -397
  18. package/.claude/agents/github/swarm-issue.md +572 -572
  19. package/.claude/agents/github/swarm-pr.md +427 -427
  20. package/.claude/agents/github/sync-coordinator.md +451 -451
  21. package/.claude/agents/github/workflow-automation.md +634 -634
  22. package/.claude/agents/goal/code-goal-planner.md +445 -445
  23. package/.claude/agents/hive-mind/collective-intelligence-coordinator.md +129 -129
  24. package/.claude/agents/hive-mind/queen-coordinator.md +202 -202
  25. package/.claude/agents/hive-mind/scout-explorer.md +241 -241
  26. package/.claude/agents/hive-mind/swarm-memory-manager.md +192 -192
  27. package/.claude/agents/hive-mind/worker-specialist.md +216 -216
  28. package/.claude/agents/neural/safla-neural.md +73 -73
  29. package/.claude/agents/reasoning/goal-planner.md +72 -72
  30. package/.claude/agents/swarm/adaptive-coordinator.md +395 -395
  31. package/.claude/agents/swarm/hierarchical-coordinator.md +326 -326
  32. package/.claude/agents/swarm/mesh-coordinator.md +391 -391
  33. package/.claude/agents/templates/migration-plan.md +745 -745
  34. package/.claude/commands/agents/agent-spawning.md +28 -28
  35. package/.claude/commands/analysis/COMMAND_COMPLIANCE_REPORT.md +53 -53
  36. package/.claude/commands/analysis/bottleneck-detect.md +162 -162
  37. package/.claude/commands/analysis/performance-bottlenecks.md +58 -58
  38. package/.claude/commands/analysis/token-efficiency.md +44 -44
  39. package/.claude/commands/automation/auto-agent.md +122 -122
  40. package/.claude/commands/automation/self-healing.md +105 -105
  41. package/.claude/commands/automation/session-memory.md +89 -89
  42. package/.claude/commands/automation/smart-agents.md +72 -72
  43. package/.claude/commands/coordination/init.md +44 -44
  44. package/.claude/commands/coordination/orchestrate.md +43 -43
  45. package/.claude/commands/coordination/spawn.md +45 -45
  46. package/.claude/commands/coordination/swarm-init.md +85 -85
  47. package/.claude/commands/github/github-modes.md +146 -146
  48. package/.claude/commands/github/github-swarm.md +121 -121
  49. package/.claude/commands/github/issue-tracker.md +291 -291
  50. package/.claude/commands/github/pr-manager.md +169 -169
  51. package/.claude/commands/github/release-manager.md +337 -337
  52. package/.claude/commands/github/repo-architect.md +366 -366
  53. package/.claude/commands/github/sync-coordinator.md +300 -300
  54. package/.claude/commands/memory/neural.md +47 -47
  55. package/.claude/commands/monitoring/agents.md +44 -44
  56. package/.claude/commands/monitoring/status.md +46 -46
  57. package/.claude/commands/optimization/auto-topology.md +61 -61
  58. package/.claude/commands/optimization/parallel-execution.md +49 -49
  59. package/.claude/commands/sparc/analyzer.md +51 -51
  60. package/.claude/commands/sparc/architect.md +53 -53
  61. package/.claude/commands/sparc/ask.md +97 -97
  62. package/.claude/commands/sparc/batch-executor.md +54 -54
  63. package/.claude/commands/sparc/code.md +89 -89
  64. package/.claude/commands/sparc/coder.md +54 -54
  65. package/.claude/commands/sparc/debug.md +83 -83
  66. package/.claude/commands/sparc/debugger.md +54 -54
  67. package/.claude/commands/sparc/designer.md +53 -53
  68. package/.claude/commands/sparc/devops.md +109 -109
  69. package/.claude/commands/sparc/docs-writer.md +80 -80
  70. package/.claude/commands/sparc/documenter.md +54 -54
  71. package/.claude/commands/sparc/innovator.md +54 -54
  72. package/.claude/commands/sparc/integration.md +83 -83
  73. package/.claude/commands/sparc/mcp.md +117 -117
  74. package/.claude/commands/sparc/memory-manager.md +54 -54
  75. package/.claude/commands/sparc/optimizer.md +54 -54
  76. package/.claude/commands/sparc/orchestrator.md +131 -131
  77. package/.claude/commands/sparc/post-deployment-monitoring-mode.md +83 -83
  78. package/.claude/commands/sparc/refinement-optimization-mode.md +83 -83
  79. package/.claude/commands/sparc/researcher.md +54 -54
  80. package/.claude/commands/sparc/reviewer.md +54 -54
  81. package/.claude/commands/sparc/security-review.md +80 -80
  82. package/.claude/commands/sparc/sparc-modes.md +174 -174
  83. package/.claude/commands/sparc/sparc.md +111 -111
  84. package/.claude/commands/sparc/spec-pseudocode.md +80 -80
  85. package/.claude/commands/sparc/supabase-admin.md +348 -348
  86. package/.claude/commands/sparc/swarm-coordinator.md +54 -54
  87. package/.claude/commands/sparc/tdd.md +54 -54
  88. package/.claude/commands/sparc/tester.md +54 -54
  89. package/.claude/commands/sparc/tutorial.md +79 -79
  90. package/.claude/commands/sparc/workflow-manager.md +54 -54
  91. package/.claude/commands/sparc.md +166 -166
  92. package/.claude/commands/swarm/analysis.md +95 -95
  93. package/.claude/commands/swarm/development.md +96 -96
  94. package/.claude/commands/swarm/examples.md +168 -168
  95. package/.claude/commands/swarm/maintenance.md +102 -102
  96. package/.claude/commands/swarm/optimization.md +117 -117
  97. package/.claude/commands/swarm/research.md +136 -136
  98. package/.claude/commands/swarm/testing.md +131 -131
  99. package/.claude/commands/training/neural-patterns.md +73 -73
  100. package/.claude/commands/training/specialization.md +62 -62
  101. package/.claude/commands/workflows/development.md +77 -77
  102. package/.claude/commands/workflows/research.md +62 -62
  103. package/.claude/guidance/{agent-bootstrap.md → shipped/agent-bootstrap.md} +126 -126
  104. package/.claude/guidance/{guidance-memory-strategy.md → shipped/guidance-memory-strategy.md} +262 -262
  105. package/.claude/guidance/{memory-strategy.md → shipped/memory-strategy.md} +204 -204
  106. package/.claude/guidance/{moflo.md → shipped/moflo.md} +45 -31
  107. package/.claude/guidance/{task-swarm-integration.md → shipped/task-swarm-integration.md} +441 -348
  108. package/.claude/helpers/gate.cjs +236 -236
  109. package/.claude/helpers/hook-handler.cjs +42 -46
  110. package/.claude/settings.json +2 -2
  111. package/.claude/settings.local.json +3 -3
  112. package/.claude/skills/fl/SKILL.md +29 -23
  113. package/.claude/skills/flo/SKILL.md +29 -23
  114. package/.claude/skills/github-code-review/SKILL.md +4 -4
  115. package/.claude/skills/github-multi-repo/SKILL.md +8 -8
  116. package/.claude/skills/github-project-management/SKILL.md +6 -6
  117. package/.claude/skills/github-release-management/SKILL.md +12 -12
  118. package/.claude/skills/github-workflow-automation/SKILL.md +6 -6
  119. package/.claude/skills/hooks-automation/SKILL.md +1201 -1201
  120. package/.claude/skills/performance-analysis/SKILL.md +563 -563
  121. package/.claude/skills/sparc-methodology/SKILL.md +64 -64
  122. package/.claude/skills/swarm-advanced/SKILL.md +77 -77
  123. package/.claude-plugin/README.md +3 -3
  124. package/.claude-plugin/docs/PLUGIN_SUMMARY.md +3 -3
  125. package/.claude-plugin/docs/QUICKSTART.md +4 -4
  126. package/.claude-plugin/marketplace.json +3 -3
  127. package/.claude-plugin/plugin.json +3 -3
  128. package/.claude-plugin/scripts/install.sh +9 -9
  129. package/.claude-plugin/scripts/verify.sh +7 -7
  130. package/README.md +311 -116
  131. package/bin/gate-hook.mjs +50 -0
  132. package/bin/gate.cjs +138 -0
  133. package/bin/hook-handler.cjs +83 -0
  134. package/bin/hooks.mjs +72 -12
  135. package/bin/index-guidance.mjs +28 -34
  136. package/bin/index-tests.mjs +710 -0
  137. package/bin/lib/process-manager.mjs +243 -0
  138. package/bin/lib/registry-cleanup.cjs +41 -0
  139. package/bin/prompt-hook.mjs +72 -0
  140. package/bin/semantic-search.mjs +473 -441
  141. package/bin/session-start-launcher.mjs +81 -31
  142. package/bin/setup-project.mjs +13 -10
  143. package/package.json +4 -2
  144. package/src/@claude-flow/cli/README.md +1 -1
  145. package/src/@claude-flow/cli/bin/cli.js +175 -175
  146. package/src/@claude-flow/cli/dist/src/commands/doctor.js +1091 -736
  147. package/src/@claude-flow/cli/dist/src/commands/github.d.ts +12 -0
  148. package/src/@claude-flow/cli/dist/src/commands/github.js +505 -0
  149. package/src/@claude-flow/cli/dist/src/commands/hive-mind.js +90 -90
  150. package/src/@claude-flow/cli/dist/src/commands/index.d.ts +1 -0
  151. package/src/@claude-flow/cli/dist/src/commands/index.js +7 -0
  152. package/src/@claude-flow/cli/dist/src/config-adapter.js +1 -1
  153. package/src/@claude-flow/cli/dist/src/init/claudemd-generator.js +1 -1
  154. package/src/@claude-flow/cli/dist/src/init/executor.js +109 -5
  155. package/src/@claude-flow/cli/dist/src/init/helpers-generator.d.ts +14 -0
  156. package/src/@claude-flow/cli/dist/src/init/helpers-generator.js +156 -24
  157. package/src/@claude-flow/cli/dist/src/init/mcp-generator.js +20 -20
  158. package/src/@claude-flow/cli/dist/src/init/moflo-init.d.ts +7 -0
  159. package/src/@claude-flow/cli/dist/src/init/moflo-init.js +72 -10
  160. package/src/@claude-flow/cli/dist/src/init/settings-generator.js +23 -14
  161. package/src/@claude-flow/cli/dist/src/mcp-server.js +3 -3
  162. package/src/@claude-flow/cli/dist/src/plugins/manager.js +9 -8
  163. package/src/@claude-flow/cli/dist/src/services/worker-daemon.d.ts +1 -0
  164. package/src/@claude-flow/cli/dist/src/services/worker-daemon.js +3 -1
  165. package/src/@claude-flow/cli/dist/src/services/workflow-gate.js +10 -10
  166. package/src/@claude-flow/cli/package.json +1 -1
@@ -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