specweave 0.26.14 → 0.27.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 (189) hide show
  1. package/CLAUDE.md +73 -1
  2. package/README.md +111 -466
  3. package/dist/plugins/specweave-jira/lib/setup-wizard.d.ts.map +1 -1
  4. package/dist/plugins/specweave-jira/lib/setup-wizard.js +57 -78
  5. package/dist/plugins/specweave-jira/lib/setup-wizard.js.map +1 -1
  6. package/dist/src/cli/commands/import-docs.d.ts.map +1 -1
  7. package/dist/src/cli/commands/import-docs.js +23 -31
  8. package/dist/src/cli/commands/import-docs.js.map +1 -1
  9. package/dist/src/cli/commands/import-external.d.ts.map +1 -1
  10. package/dist/src/cli/commands/import-external.js +6 -10
  11. package/dist/src/cli/commands/import-external.js.map +1 -1
  12. package/dist/src/cli/commands/init-multiproject.d.ts.map +1 -1
  13. package/dist/src/cli/commands/init-multiproject.js +58 -73
  14. package/dist/src/cli/commands/init-multiproject.js.map +1 -1
  15. package/dist/src/cli/commands/init.d.ts +17 -11
  16. package/dist/src/cli/commands/init.d.ts.map +1 -1
  17. package/dist/src/cli/commands/init.js +221 -1874
  18. package/dist/src/cli/commands/init.js.map +1 -1
  19. package/dist/src/cli/commands/install.d.ts.map +1 -1
  20. package/dist/src/cli/commands/install.js +14 -22
  21. package/dist/src/cli/commands/install.js.map +1 -1
  22. package/dist/src/cli/commands/migrate-config.d.ts.map +1 -1
  23. package/dist/src/cli/commands/migrate-config.js +6 -10
  24. package/dist/src/cli/commands/migrate-config.js.map +1 -1
  25. package/dist/src/cli/commands/switch-project.d.ts.map +1 -1
  26. package/dist/src/cli/commands/switch-project.js.map +1 -1
  27. package/dist/src/cli/helpers/ado-area-path-mapper.d.ts.map +1 -1
  28. package/dist/src/cli/helpers/ado-area-path-mapper.js +36 -49
  29. package/dist/src/cli/helpers/ado-area-path-mapper.js.map +1 -1
  30. package/dist/src/cli/helpers/github/increment-profile-selector.d.ts.map +1 -1
  31. package/dist/src/cli/helpers/github/increment-profile-selector.js.map +1 -1
  32. package/dist/src/cli/helpers/github/profile-manager.d.ts.map +1 -1
  33. package/dist/src/cli/helpers/github/profile-manager.js +8 -11
  34. package/dist/src/cli/helpers/github/profile-manager.js.map +1 -1
  35. package/dist/src/cli/helpers/github-repo-selector.d.ts.map +1 -1
  36. package/dist/src/cli/helpers/github-repo-selector.js +26 -50
  37. package/dist/src/cli/helpers/github-repo-selector.js.map +1 -1
  38. package/dist/src/cli/helpers/import-strategy-prompter.d.ts.map +1 -1
  39. package/dist/src/cli/helpers/import-strategy-prompter.js +39 -52
  40. package/dist/src/cli/helpers/import-strategy-prompter.js.map +1 -1
  41. package/dist/src/cli/helpers/init/config-detection.d.ts +40 -0
  42. package/dist/src/cli/helpers/init/config-detection.d.ts.map +1 -0
  43. package/dist/src/cli/helpers/init/config-detection.js +125 -0
  44. package/dist/src/cli/helpers/init/config-detection.js.map +1 -0
  45. package/dist/src/cli/helpers/init/directory-structure.d.ts +26 -0
  46. package/dist/src/cli/helpers/init/directory-structure.d.ts.map +1 -0
  47. package/dist/src/cli/helpers/init/directory-structure.js +190 -0
  48. package/dist/src/cli/helpers/init/directory-structure.js.map +1 -0
  49. package/dist/src/cli/helpers/init/external-import.d.ts +15 -0
  50. package/dist/src/cli/helpers/init/external-import.d.ts.map +1 -0
  51. package/dist/src/cli/helpers/init/external-import.js +251 -0
  52. package/dist/src/cli/helpers/init/external-import.js.map +1 -0
  53. package/dist/src/cli/helpers/init/index.d.ts +15 -0
  54. package/dist/src/cli/helpers/init/index.d.ts.map +1 -0
  55. package/dist/src/cli/helpers/init/index.js +26 -0
  56. package/dist/src/cli/helpers/init/index.js.map +1 -0
  57. package/dist/src/cli/helpers/init/next-steps.d.ts +15 -0
  58. package/dist/src/cli/helpers/init/next-steps.d.ts.map +1 -0
  59. package/dist/src/cli/helpers/init/next-steps.js +72 -0
  60. package/dist/src/cli/helpers/init/next-steps.js.map +1 -0
  61. package/dist/src/cli/helpers/init/path-utils.d.ts +41 -0
  62. package/dist/src/cli/helpers/init/path-utils.d.ts.map +1 -0
  63. package/dist/src/cli/helpers/init/path-utils.js +146 -0
  64. package/dist/src/cli/helpers/init/path-utils.js.map +1 -0
  65. package/dist/src/cli/helpers/init/plugin-installer.d.ts +28 -0
  66. package/dist/src/cli/helpers/init/plugin-installer.d.ts.map +1 -0
  67. package/dist/src/cli/helpers/init/plugin-installer.js +238 -0
  68. package/dist/src/cli/helpers/init/plugin-installer.js.map +1 -0
  69. package/dist/src/cli/helpers/init/repository-setup.d.ts +28 -0
  70. package/dist/src/cli/helpers/init/repository-setup.d.ts.map +1 -0
  71. package/dist/src/cli/helpers/init/repository-setup.js +78 -0
  72. package/dist/src/cli/helpers/init/repository-setup.js.map +1 -0
  73. package/dist/src/cli/helpers/init/smart-reinit.d.ts +30 -0
  74. package/dist/src/cli/helpers/init/smart-reinit.d.ts.map +1 -0
  75. package/dist/src/cli/helpers/init/smart-reinit.js +140 -0
  76. package/dist/src/cli/helpers/init/smart-reinit.js.map +1 -0
  77. package/dist/src/cli/helpers/init/testing-config.d.ts +27 -0
  78. package/dist/src/cli/helpers/init/testing-config.d.ts.map +1 -0
  79. package/dist/src/cli/helpers/init/testing-config.js +131 -0
  80. package/dist/src/cli/helpers/init/testing-config.js.map +1 -0
  81. package/dist/src/cli/helpers/init/types.d.ts +86 -0
  82. package/dist/src/cli/helpers/init/types.d.ts.map +1 -0
  83. package/dist/src/cli/helpers/init/types.js +5 -0
  84. package/dist/src/cli/helpers/init/types.js.map +1 -0
  85. package/dist/src/cli/helpers/issue-tracker/ado-auto-discover.d.ts.map +1 -1
  86. package/dist/src/cli/helpers/issue-tracker/ado-auto-discover.js +10 -12
  87. package/dist/src/cli/helpers/issue-tracker/ado-auto-discover.js.map +1 -1
  88. package/dist/src/cli/helpers/issue-tracker/ado.d.ts.map +1 -1
  89. package/dist/src/cli/helpers/issue-tracker/ado.js +43 -60
  90. package/dist/src/cli/helpers/issue-tracker/ado.js.map +1 -1
  91. package/dist/src/cli/helpers/issue-tracker/github-multi-repo.d.ts.map +1 -1
  92. package/dist/src/cli/helpers/issue-tracker/github-multi-repo.js +193 -230
  93. package/dist/src/cli/helpers/issue-tracker/github-multi-repo.js.map +1 -1
  94. package/dist/src/cli/helpers/issue-tracker/github.d.ts.map +1 -1
  95. package/dist/src/cli/helpers/issue-tracker/github.js +43 -54
  96. package/dist/src/cli/helpers/issue-tracker/github.js.map +1 -1
  97. package/dist/src/cli/helpers/issue-tracker/index.d.ts.map +1 -1
  98. package/dist/src/cli/helpers/issue-tracker/index.js +27 -40
  99. package/dist/src/cli/helpers/issue-tracker/index.js.map +1 -1
  100. package/dist/src/cli/helpers/issue-tracker/jira.d.ts.map +1 -1
  101. package/dist/src/cli/helpers/issue-tracker/jira.js +54 -70
  102. package/dist/src/cli/helpers/issue-tracker/jira.js.map +1 -1
  103. package/dist/src/cli/helpers/smart-filter.d.ts.map +1 -1
  104. package/dist/src/cli/helpers/smart-filter.js +62 -85
  105. package/dist/src/cli/helpers/smart-filter.js.map +1 -1
  106. package/dist/src/core/increment/auto-transition-manager.d.ts +12 -0
  107. package/dist/src/core/increment/auto-transition-manager.d.ts.map +1 -1
  108. package/dist/src/core/increment/auto-transition-manager.js +45 -0
  109. package/dist/src/core/increment/auto-transition-manager.js.map +1 -1
  110. package/dist/src/core/increment/metadata-manager.d.ts.map +1 -1
  111. package/dist/src/core/increment/metadata-manager.js +46 -0
  112. package/dist/src/core/increment/metadata-manager.js.map +1 -1
  113. package/dist/src/core/increment/status-change-sync-trigger.d.ts +12 -0
  114. package/dist/src/core/increment/status-change-sync-trigger.d.ts.map +1 -1
  115. package/dist/src/core/increment/status-change-sync-trigger.js +48 -2
  116. package/dist/src/core/increment/status-change-sync-trigger.js.map +1 -1
  117. package/dist/src/core/living-docs/living-docs-sync.d.ts +13 -0
  118. package/dist/src/core/living-docs/living-docs-sync.d.ts.map +1 -1
  119. package/dist/src/core/living-docs/living-docs-sync.js +40 -0
  120. package/dist/src/core/living-docs/living-docs-sync.js.map +1 -1
  121. package/dist/src/core/repo-structure/repo-bulk-discovery.d.ts.map +1 -1
  122. package/dist/src/core/repo-structure/repo-bulk-discovery.js +63 -83
  123. package/dist/src/core/repo-structure/repo-bulk-discovery.js.map +1 -1
  124. package/dist/src/core/repo-structure/repo-structure-manager.d.ts.map +1 -1
  125. package/dist/src/core/repo-structure/repo-structure-manager.js +339 -424
  126. package/dist/src/core/repo-structure/repo-structure-manager.js.map +1 -1
  127. package/dist/src/core/sync/bidirectional-engine.d.ts.map +1 -1
  128. package/dist/src/core/sync/bidirectional-engine.js +21 -29
  129. package/dist/src/core/sync/bidirectional-engine.js.map +1 -1
  130. package/dist/src/init/InitFlow.js +15 -19
  131. package/dist/src/init/InitFlow.js.map +1 -1
  132. package/dist/src/init/repo/types.d.ts +1 -1
  133. package/dist/src/integrations/ado/area-path-mapper.d.ts.map +1 -1
  134. package/dist/src/integrations/ado/area-path-mapper.js +19 -23
  135. package/dist/src/integrations/ado/area-path-mapper.js.map +1 -1
  136. package/dist/src/utils/external-resource-validator.d.ts.map +1 -1
  137. package/dist/src/utils/external-resource-validator.js +41 -65
  138. package/dist/src/utils/external-resource-validator.js.map +1 -1
  139. package/dist/src/utils/project-detection.d.ts.map +1 -1
  140. package/dist/src/utils/project-detection.js +19 -21
  141. package/dist/src/utils/project-detection.js.map +1 -1
  142. package/dist/src/utils/project-validator.d.ts.map +1 -1
  143. package/dist/src/utils/project-validator.js +5 -7
  144. package/dist/src/utils/project-validator.js.map +1 -1
  145. package/package.json +2 -3
  146. package/plugins/specweave/agents/tech-lead/AGENT.md +9 -0
  147. package/plugins/specweave/hooks/docs-changed.sh.backup +79 -0
  148. package/plugins/specweave/hooks/human-input-required.sh.backup +75 -0
  149. package/plugins/specweave/hooks/post-first-increment.sh.backup +61 -0
  150. package/plugins/specweave/hooks/post-increment-change.sh.backup +98 -0
  151. package/plugins/specweave/hooks/post-increment-completion.sh.backup +231 -0
  152. package/plugins/specweave/hooks/post-increment-planning.sh.backup +1048 -0
  153. package/plugins/specweave/hooks/post-increment-status-change.sh.backup +147 -0
  154. package/plugins/specweave/hooks/post-spec-update.sh.backup +158 -0
  155. package/plugins/specweave/hooks/post-user-story-complete.sh.backup +179 -0
  156. package/plugins/specweave/hooks/pre-command-deduplication.sh.backup +83 -0
  157. package/plugins/specweave/hooks/pre-implementation.sh.backup +67 -0
  158. package/plugins/specweave/hooks/pre-task-completion.sh.backup +194 -0
  159. package/plugins/specweave/hooks/pre-tool-use.sh.backup +133 -0
  160. package/plugins/specweave/hooks/user-prompt-submit.sh.backup +386 -0
  161. package/plugins/specweave/lib/vendor/core/increment/auto-transition-manager.d.ts +12 -0
  162. package/plugins/specweave/lib/vendor/core/increment/auto-transition-manager.js +45 -0
  163. package/plugins/specweave/lib/vendor/core/increment/auto-transition-manager.js.map +1 -1
  164. package/plugins/specweave/lib/vendor/core/increment/metadata-manager.js +46 -0
  165. package/plugins/specweave/lib/vendor/core/increment/metadata-manager.js.map +1 -1
  166. package/plugins/specweave/skills/increment-planner/SKILL.md +10 -5
  167. package/plugins/specweave/skills/specweave-framework/SKILL.md +6 -4
  168. package/plugins/specweave/templates/coding-standards.md.template +36 -0
  169. package/plugins/specweave-ado/hooks/post-living-docs-update.sh.backup +353 -0
  170. package/plugins/specweave-ado/hooks/post-task-completion.sh.backup +172 -0
  171. package/plugins/specweave-ado/lib/ado-multi-project-sync.js +1 -0
  172. package/plugins/specweave-ado/lib/enhanced-ado-sync.js +170 -0
  173. package/plugins/specweave-ado/lib/project-selector.js +56 -67
  174. package/plugins/specweave-ado/lib/project-selector.ts +72 -85
  175. package/plugins/specweave-github/hooks/.specweave/logs/hooks-debug.log +1104 -0
  176. package/plugins/specweave-github/hooks/post-task-completion.sh.backup +258 -0
  177. package/plugins/specweave-github/lib/repo-selector.js +55 -66
  178. package/plugins/specweave-github/lib/repo-selector.ts +73 -84
  179. package/plugins/specweave-jira/commands/import-projects.js +3 -5
  180. package/plugins/specweave-jira/commands/import-projects.ts +3 -5
  181. package/plugins/specweave-jira/hooks/post-task-completion.sh.backup +172 -0
  182. package/plugins/specweave-jira/lib/enhanced-jira-sync.js +3 -3
  183. package/plugins/specweave-jira/lib/project-selector.js +60 -71
  184. package/plugins/specweave-jira/lib/project-selector.ts +78 -91
  185. package/plugins/specweave-jira/lib/setup-wizard.js +51 -72
  186. package/plugins/specweave-jira/lib/setup-wizard.ts +56 -74
  187. package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +1017 -0
  188. package/plugins/specweave-release/hooks/post-task-completion.sh.backup +110 -0
  189. package/src/templates/CLAUDE.md.template +14 -0
@@ -17,7 +17,7 @@
17
17
  import { existsSync, mkdirSync, writeFileSync } from 'fs';
18
18
  import path from 'path';
19
19
  import chalk from 'chalk';
20
- import inquirer from 'inquirer';
20
+ import { select, input, confirm, number } from '@inquirer/prompts';
21
21
  import ora from 'ora';
22
22
  import { execSync } from 'child_process';
23
23
  import { execFileNoThrowSync } from '../../utils/execFileNoThrow.js';
@@ -54,12 +54,10 @@ export class RepoStructureManager {
54
54
  console.log(chalk.yellow('\nāøļø Detected interrupted setup!'));
55
55
  console.log(chalk.gray(` Last step: ${resumedState.currentStep}`));
56
56
  console.log(chalk.gray(` Time: ${new Date(resumedState.timestamp).toLocaleString()}\n`));
57
- const { shouldResume } = await inquirer.prompt([{
58
- type: 'confirm',
59
- name: 'shouldResume',
60
- message: 'Resume previous setup?',
61
- default: true
62
- }]);
57
+ const shouldResume = await confirm({
58
+ message: 'Resume previous setup?',
59
+ default: true
60
+ });
63
61
  if (shouldResume) {
64
62
  return this.resumeSetup(resumedState);
65
63
  }
@@ -78,38 +76,31 @@ export class RepoStructureManager {
78
76
  else {
79
77
  // Ask user for architecture choice
80
78
  const promptData = getArchitecturePrompt();
81
- const result = await inquirer.prompt([{
82
- type: 'select',
83
- name: 'architecture',
84
- message: promptData.question,
85
- choices: promptData.options.map(opt => ({
86
- name: `${opt.label}\n${chalk.gray(opt.description)}\n${chalk.dim(opt.example)}`,
87
- value: opt.value,
88
- short: opt.label
89
- })),
90
- default: 'single'
91
- }]);
92
- architecture = result.architecture;
79
+ architecture = await select({
80
+ message: promptData.question,
81
+ choices: promptData.options.map(opt => ({
82
+ name: `${opt.label}\n${chalk.gray(opt.description)}\n${chalk.dim(opt.example)}`,
83
+ value: opt.value
84
+ })),
85
+ default: 'single'
86
+ });
93
87
  }
94
88
  // Step 2: Ask about Git hosting platform
95
89
  const registry = getPlatformRegistry();
96
90
  const platformOptions = registry.getPlatformOptions(true); // Include unsupported platforms
97
91
  const platformPromptData = getPlatformSelectionPrompt();
98
92
  console.log(chalk.cyan('\n' + platformPromptData.message));
99
- const { platform } = await inquirer.prompt([{
100
- type: 'select',
101
- name: 'platform',
102
- message: platformPromptData.question,
103
- choices: platformOptions.map(opt => ({
104
- name: opt.disabled
105
- ? `${opt.name}\n${chalk.gray(opt.description)}\n${chalk.yellow('āš ļø ' + opt.disabled)}`
106
- : `${opt.name}\n${chalk.gray(opt.description)}`,
107
- value: opt.value,
108
- short: opt.name,
109
- disabled: opt.disabled ? opt.disabled : false
110
- })),
111
- default: 'github'
112
- }]);
93
+ const platform = await select({
94
+ message: platformPromptData.question,
95
+ choices: platformOptions.map(opt => ({
96
+ name: opt.disabled
97
+ ? `${opt.name}\n${chalk.gray(opt.description)}\n${chalk.yellow('āš ļø ' + opt.disabled)}`
98
+ : `${opt.name}\n${chalk.gray(opt.description)}`,
99
+ value: opt.value,
100
+ disabled: opt.disabled ? opt.disabled : false
101
+ })),
102
+ default: 'github'
103
+ });
113
104
  // Get provider instance
114
105
  const provider = registry.getProvider(platform);
115
106
  if (!provider) {
@@ -118,17 +109,14 @@ export class RepoStructureManager {
118
109
  console.log(chalk.green(`\nāœ“ Using ${provider.config.name} as Git hosting platform\n`));
119
110
  // Step 3: Ask about Git remote URL format (SSH vs HTTPS)
120
111
  const urlTypePromptData = getUrlTypePrompt();
121
- const { urlType } = await inquirer.prompt([{
122
- type: 'select',
123
- name: 'urlType',
124
- message: urlTypePromptData.question,
125
- choices: urlTypePromptData.options.map(opt => ({
126
- name: `${opt.label}\n${chalk.gray(opt.description)}`,
127
- value: opt.value,
128
- short: opt.label
129
- })),
130
- default: urlTypePromptData.default
131
- }]);
112
+ const urlType = await select({
113
+ message: urlTypePromptData.question,
114
+ choices: urlTypePromptData.options.map(opt => ({
115
+ name: `${opt.label}\n${chalk.gray(opt.description)}`,
116
+ value: opt.value
117
+ })),
118
+ default: urlTypePromptData.default
119
+ });
132
120
  console.log(chalk.green(`\nāœ“ Using ${urlType.toUpperCase()} remote URLs\n`));
133
121
  // Map ArchitectureChoice to internal architecture
134
122
  const mappedArch = this.mapArchitectureChoice(architecture);
@@ -222,12 +210,10 @@ export class RepoStructureManager {
222
210
  const owner = match[1];
223
211
  const repo = match[2];
224
212
  console.log(chalk.green(`āœ“ Existing repository detected: ${owner}/${repo}`));
225
- const { useExisting } = await inquirer.prompt([{
226
- type: 'confirm',
227
- name: 'useExisting',
228
- message: 'Use existing repository?',
229
- default: true
230
- }]);
213
+ const useExisting = await confirm({
214
+ message: 'Use existing repository?',
215
+ default: true
216
+ });
231
217
  if (useExisting) {
232
218
  // Fetch description and visibility from GitHub API
233
219
  let description = `${repo} - SpecWeave project`;
@@ -274,49 +260,41 @@ export class RepoStructureManager {
274
260
  }
275
261
  }
276
262
  // Manual configuration
277
- const answers = await inquirer.prompt([
278
- {
279
- type: 'input',
280
- name: 'owner',
281
- message: 'GitHub owner/organization:',
282
- validate: (input) => !!input.trim() || 'Owner is required'
283
- },
284
- {
285
- type: 'input',
286
- name: 'repo',
287
- message: 'Repository name:',
288
- default: path.basename(this.projectPath),
289
- validate: (input) => !!input.trim() || 'Repository name is required'
290
- },
291
- {
292
- type: 'input',
293
- name: 'description',
294
- message: 'Repository description:',
295
- default: 'My SpecWeave project'
296
- },
297
- {
298
- type: 'confirm',
299
- name: 'createOnGitHub',
300
- message: 'Create repository on GitHub?',
301
- default: !hasGit
302
- }
303
- ]);
263
+ const ownerAnswer = await input({
264
+ message: 'GitHub owner/organization:',
265
+ validate: (val) => !!val.trim() || 'Owner is required'
266
+ });
267
+ const repoAnswer = await input({
268
+ message: 'Repository name:',
269
+ default: path.basename(this.projectPath),
270
+ validate: (val) => !!val.trim() || 'Repository name is required'
271
+ });
272
+ const descriptionAnswer = await input({
273
+ message: 'Repository description:',
274
+ default: 'My SpecWeave project'
275
+ });
276
+ const createOnGitHubAnswer = await confirm({
277
+ message: 'Create repository on GitHub?',
278
+ default: !hasGit
279
+ });
280
+ const answers = {
281
+ owner: ownerAnswer,
282
+ repo: repoAnswer,
283
+ description: descriptionAnswer,
284
+ createOnGitHub: createOnGitHubAnswer
285
+ };
304
286
  // Ask about visibility only if creating a new repository
305
287
  let visibility = 'private';
306
288
  if (answers.createOnGitHub) {
307
289
  const visibilityPrompt = getVisibilityPrompt(answers.repo);
308
- const result = await inquirer.prompt([{
309
- type: 'select',
310
- name: 'visibility',
311
- message: visibilityPrompt.question,
312
- choices: visibilityPrompt.options.map(opt => ({
313
- name: `${opt.label}\n${chalk.gray(opt.description)}`,
314
- value: opt.value,
315
- short: opt.label
316
- })),
317
- default: visibilityPrompt.default
318
- }]);
319
- visibility = result.visibility;
290
+ visibility = await select({
291
+ message: visibilityPrompt.question,
292
+ choices: visibilityPrompt.options.map(opt => ({
293
+ name: `${opt.label}\n${chalk.gray(opt.description)}`,
294
+ value: opt.value
295
+ })),
296
+ default: visibilityPrompt.default
297
+ });
320
298
  }
321
299
  return {
322
300
  architecture: 'single',
@@ -380,65 +358,54 @@ export class RepoStructureManager {
380
358
  if (!isLocalParent && this.githubToken && useParent) {
381
359
  console.log(chalk.cyan('\nšŸš€ Repository Discovery\n'));
382
360
  console.log(chalk.gray('You\'re setting up multiple repositories. We can discover them automatically!\n'));
383
- const { configMethod } = await inquirer.prompt([
384
- {
385
- type: 'select',
386
- name: 'configMethod',
387
- message: 'How do you want to configure repositories?',
388
- choices: [
389
- {
390
- name: [
391
- chalk.bold.green('šŸŽÆ Bulk Discovery (RECOMMENDED)'),
392
- chalk.gray(' Automatically discover repos from ' + provider.config.name),
393
- chalk.gray(' • Select parent from discovered list'),
394
- chalk.gray(' • Auto-configure implementation repos'),
395
- chalk.gray(' • Supports: all, pattern, regex filtering'),
396
- ''
397
- ].join('\n'),
398
- value: 'bulk-discovery',
399
- short: 'Bulk Discovery'
400
- },
401
- {
402
- name: [
403
- chalk.bold('āœļø Manual Entry'),
404
- chalk.gray(' Enter each repository manually'),
405
- chalk.gray(' • Full control over settings'),
406
- chalk.gray(' • Best for new repos or custom setup'),
407
- ''
408
- ].join('\n'),
409
- value: 'manual',
410
- short: 'Manual'
411
- }
412
- ],
413
- default: 'bulk-discovery' // Make bulk discovery the default!
414
- }
415
- ]);
361
+ const configMethod = await select({
362
+ message: 'How do you want to configure repositories?',
363
+ choices: [
364
+ {
365
+ name: [
366
+ chalk.bold.green('šŸŽÆ Bulk Discovery (RECOMMENDED)'),
367
+ chalk.gray(' Automatically discover repos from ' + provider.config.name),
368
+ chalk.gray(' • Select parent from discovered list'),
369
+ chalk.gray(' • Auto-configure implementation repos'),
370
+ chalk.gray(' • Supports: all, pattern, regex filtering'),
371
+ ''
372
+ ].join('\n'),
373
+ value: 'bulk-discovery'
374
+ },
375
+ {
376
+ name: [
377
+ chalk.bold('āœļø Manual Entry'),
378
+ chalk.gray(' Enter each repository manually'),
379
+ chalk.gray(' • Full control over settings'),
380
+ chalk.gray(' • Best for new repos or custom setup'),
381
+ ''
382
+ ].join('\n'),
383
+ value: 'manual'
384
+ }
385
+ ],
386
+ default: 'bulk-discovery'
387
+ });
416
388
  discoveryStrategy = configMethod;
417
389
  }
418
390
  // Step 2: If bulk discovery, discover repos FIRST, then ask which is parent
419
391
  if (discoveryStrategy === 'bulk-discovery') {
420
392
  // Get owner FIRST (needed for discovery)
421
393
  console.log(chalk.cyan('\nšŸ‘¤ Repository Owner\n'));
422
- const ownerPrompt = await inquirer.prompt([
423
- {
424
- type: 'input',
425
- name: 'owner',
426
- message: `${provider.config.name} owner/organization:`,
427
- validate: async (input) => {
428
- if (!input.trim())
429
- return 'Owner is required';
430
- // Validate owner exists on the platform
431
- if (this.githubToken) {
432
- const result = await provider.validateOwner(input, this.githubToken);
433
- if (!result.valid) {
434
- return result.error || `Invalid ${provider.config.name} owner`;
435
- }
394
+ owner = await input({
395
+ message: `${provider.config.name} owner/organization:`,
396
+ validate: async (val) => {
397
+ if (!val.trim())
398
+ return 'Owner is required';
399
+ // Validate owner exists on the platform
400
+ if (this.githubToken) {
401
+ const result = await provider.validateOwner(val, this.githubToken);
402
+ if (!result.valid) {
403
+ return result.error || `Invalid ${provider.config.name} owner`;
436
404
  }
437
- return true;
438
405
  }
406
+ return true;
439
407
  }
440
- ]);
441
- owner = ownerPrompt.owner;
408
+ });
442
409
  // Discover repositories via pattern matching
443
410
  const octokit = new Octokit({ auth: this.githubToken });
444
411
  const isOrg = await provider.isOrganization(owner, this.githubToken);
@@ -466,15 +433,11 @@ export class RepoStructureManager {
466
433
  short: 'Enter manually'
467
434
  }
468
435
  ];
469
- const { parentSelection } = await inquirer.prompt([
470
- {
471
- type: 'select',
472
- name: 'parentSelection',
473
- message: 'Which repository is the parent?',
474
- choices: parentChoices,
475
- pageSize: 15
476
- }
477
- ]);
436
+ const parentSelection = await select({
437
+ message: 'Which repository is the parent?',
438
+ choices: parentChoices,
439
+ pageSize: 15
440
+ });
478
441
  if (parentSelection === 'manual') {
479
442
  // User wants to enter parent manually - fall back to old flow
480
443
  discoveryStrategy = 'manual';
@@ -541,106 +504,92 @@ export class RepoStructureManager {
541
504
  // Local parent: Skip GitHub questions, just ask for folder name
542
505
  console.log(chalk.blue('\nšŸ’” Local Parent Folder Setup'));
543
506
  console.log(chalk.gray('This folder will contain .specweave/ but will NOT be pushed to GitHub.\n'));
544
- parentAnswers = await inquirer.prompt([
545
- {
546
- type: 'input',
547
- name: 'parentName',
548
- message: 'Parent folder name:',
549
- default: `${path.basename(this.projectPath)}`,
550
- validate: (input) => {
551
- if (!input.trim())
552
- return 'Folder name is required';
553
- return true;
554
- }
555
- },
556
- {
557
- type: 'input',
558
- name: 'owner',
559
- message: `${provider.config.name} owner/organization for IMPLEMENTATION repos:`,
560
- validate: async (input) => {
561
- if (!input.trim())
562
- return 'Owner is required';
563
- // Validate owner exists on the platform
564
- if (this.githubToken) {
565
- const result = await provider.validateOwner(input, this.githubToken);
566
- if (!result.valid) {
567
- return result.error || `Invalid ${provider.config.name} owner`;
568
- }
507
+ const parentNameAnswer = await input({
508
+ message: 'Parent folder name:',
509
+ default: `${path.basename(this.projectPath)}`,
510
+ validate: (val) => {
511
+ if (!val.trim())
512
+ return 'Folder name is required';
513
+ return true;
514
+ }
515
+ });
516
+ const ownerForLocalAnswer = await input({
517
+ message: `${provider.config.name} owner/organization for IMPLEMENTATION repos:`,
518
+ validate: async (val) => {
519
+ if (!val.trim())
520
+ return 'Owner is required';
521
+ // Validate owner exists on the platform
522
+ if (this.githubToken) {
523
+ const result = await provider.validateOwner(val, this.githubToken);
524
+ if (!result.valid) {
525
+ return result.error || `Invalid ${provider.config.name} owner`;
569
526
  }
570
- return true;
571
527
  }
528
+ return true;
572
529
  }
573
- ]);
530
+ });
531
+ parentAnswers = {
532
+ parentName: parentNameAnswer,
533
+ owner: ownerForLocalAnswer
534
+ };
574
535
  // Set defaults for local parent
575
536
  parentAnswers.description = 'Local parent folder (not synced to GitHub)';
576
537
  parentAnswers.createOnGitHub = false; // Never create GitHub repo for local parent
577
538
  }
578
539
  else {
579
540
  // GitHub parent: First ask if using existing or creating new
580
- const { parentChoice } = await inquirer.prompt([
581
- {
582
- type: 'select',
583
- name: 'parentChoice',
584
- message: 'Parent repository setup:',
585
- choices: [
586
- {
587
- name: `${chalk.green('Use existing parent repository')}\n${chalk.gray('Connect to an existing GitHub repo that already has .specweave/ structure')}`,
588
- value: 'existing',
589
- short: 'Use existing'
590
- },
591
- {
592
- name: `${chalk.blue('Create new parent repository')}\n${chalk.gray('Create a new GitHub repo for specs, docs, and architecture')}`,
593
- value: 'new',
594
- short: 'Create new'
595
- }
596
- ],
597
- default: 'new'
598
- }
599
- ]);
541
+ const parentChoice = await select({
542
+ message: 'Parent repository setup:',
543
+ choices: [
544
+ {
545
+ name: `${chalk.green('Use existing parent repository')}\n${chalk.gray('Connect to an existing GitHub repo that already has .specweave/ structure')}`,
546
+ value: 'existing'
547
+ },
548
+ {
549
+ name: `${chalk.blue('Create new parent repository')}\n${chalk.gray('Create a new GitHub repo for specs, docs, and architecture')}`,
550
+ value: 'new'
551
+ }
552
+ ],
553
+ default: 'new'
554
+ });
600
555
  if (parentChoice === 'existing') {
601
556
  // Using existing parent repository
602
557
  console.log(chalk.cyan('\nšŸ“‹ Existing Parent Repository\n'));
603
558
  // Ask for owner first
604
- const ownerPrompt = await inquirer.prompt([
605
- {
606
- type: 'input',
607
- name: 'owner',
608
- message: `${provider.config.name} owner/organization:`,
609
- validate: async (input) => {
610
- if (!input.trim())
611
- return 'Owner is required';
612
- // Validate owner exists on the platform
613
- if (this.githubToken) {
614
- const result = await provider.validateOwner(input, this.githubToken);
615
- if (!result.valid) {
616
- return result.error || `Invalid ${provider.config.name} owner`;
617
- }
559
+ const existingOwner = await input({
560
+ message: `${provider.config.name} owner/organization:`,
561
+ validate: async (val) => {
562
+ if (!val.trim())
563
+ return 'Owner is required';
564
+ // Validate owner exists on the platform
565
+ if (this.githubToken) {
566
+ const result = await provider.validateOwner(val, this.githubToken);
567
+ if (!result.valid) {
568
+ return result.error || `Invalid ${provider.config.name} owner`;
618
569
  }
619
- return true;
620
570
  }
571
+ return true;
621
572
  }
622
- ]);
573
+ });
574
+ const ownerPrompt = { owner: existingOwner };
623
575
  // Ask for existing repo name
624
- const repoPrompt = await inquirer.prompt([
625
- {
626
- type: 'input',
627
- name: 'parentName',
628
- message: 'Existing parent repository name:',
629
- default: `${path.basename(this.projectPath)}-parent`,
630
- validate: async (input) => {
631
- if (!input.trim())
632
- return 'Repository name is required';
633
- // Validate repository EXISTS on the platform
634
- if (this.githubToken && ownerPrompt.owner) {
635
- const result = await provider.validateRepository(ownerPrompt.owner, input, this.githubToken);
636
- if (!result.exists) {
637
- return `Repository ${ownerPrompt.owner}/${input} not found on ${provider.config.name}. Please check the name or choose 'Create new'.`;
638
- }
576
+ const existingParentName = await input({
577
+ message: 'Existing parent repository name:',
578
+ default: `${path.basename(this.projectPath)}-parent`,
579
+ validate: async (val) => {
580
+ if (!val.trim())
581
+ return 'Repository name is required';
582
+ // Validate repository EXISTS on the platform
583
+ if (this.githubToken && ownerPrompt.owner) {
584
+ const result = await provider.validateRepository(ownerPrompt.owner, val, this.githubToken);
585
+ if (!result.exists) {
586
+ return `Repository ${ownerPrompt.owner}/${val} not found on ${provider.config.name}. Please check the name or choose 'Create new'.`;
639
587
  }
640
- return true;
641
588
  }
589
+ return true;
642
590
  }
643
- ]);
591
+ });
592
+ const repoPrompt = { parentName: existingParentName };
644
593
  // Fetch description and visibility from GitHub API (or use defaults)
645
594
  let description = 'SpecWeave parent repository - specs, docs, and architecture';
646
595
  let existingVisibility = 'private';
@@ -675,60 +624,54 @@ export class RepoStructureManager {
675
624
  // Creating new parent repository
676
625
  console.log(chalk.cyan('\n✨ New Parent Repository\n'));
677
626
  // Ask for owner (separate prompt to avoid validator issues)
678
- const ownerPrompt = await inquirer.prompt([
679
- {
680
- type: 'input',
681
- name: 'owner',
682
- message: `${provider.config.name} owner/organization for ALL repos:`,
683
- validate: async (input) => {
684
- if (!input.trim())
685
- return 'Owner is required';
686
- // Validate owner exists on the platform
687
- if (this.githubToken) {
688
- const result = await provider.validateOwner(input, this.githubToken);
689
- if (!result.valid) {
690
- return result.error || `Invalid ${provider.config.name} owner`;
691
- }
627
+ const newOwner = await input({
628
+ message: `${provider.config.name} owner/organization for ALL repos:`,
629
+ validate: async (val) => {
630
+ if (!val.trim())
631
+ return 'Owner is required';
632
+ // Validate owner exists on the platform
633
+ if (this.githubToken) {
634
+ const result = await provider.validateOwner(val, this.githubToken);
635
+ if (!result.valid) {
636
+ return result.error || `Invalid ${provider.config.name} owner`;
692
637
  }
693
- return true;
694
638
  }
639
+ return true;
695
640
  }
696
- ]);
641
+ });
642
+ const ownerPrompt = { owner: newOwner };
697
643
  // Now ask remaining questions, using the owner value
698
- const remainingAnswers = await inquirer.prompt([
699
- {
700
- type: 'input',
701
- name: 'parentName',
702
- message: 'Parent repository name:',
703
- default: `${path.basename(this.projectPath)}-parent`,
704
- validate: async (input) => {
705
- if (!input.trim())
706
- return 'Repository name is required';
707
- // Validate repository DOESN'T exist
708
- if (this.githubToken && ownerPrompt.owner) {
709
- const result = await provider.validateRepository(ownerPrompt.owner, input, this.githubToken);
710
- if (result.exists) {
711
- return `Repository ${ownerPrompt.owner}/${input} already exists at ${result.url}. Please choose 'Use existing' or pick a different name.`;
712
- }
644
+ const newParentName = await input({
645
+ message: 'Parent repository name:',
646
+ default: `${path.basename(this.projectPath)}-parent`,
647
+ validate: async (val) => {
648
+ if (!val.trim())
649
+ return 'Repository name is required';
650
+ // Validate repository DOESN'T exist
651
+ if (this.githubToken && ownerPrompt.owner) {
652
+ const result = await provider.validateRepository(ownerPrompt.owner, val, this.githubToken);
653
+ if (result.exists) {
654
+ return `Repository ${ownerPrompt.owner}/${val} already exists at ${result.url}. Please choose 'Use existing' or pick a different name.`;
713
655
  }
714
- return true;
715
656
  }
716
- },
717
- {
718
- type: 'input',
719
- name: 'description',
720
- message: 'Parent repository description:',
721
- default: 'SpecWeave parent repository - specs, docs, and architecture'
722
- },
723
- {
724
- type: 'confirm',
725
- name: 'createOnGitHub',
726
- message: 'Create parent repository on GitHub?',
727
- default: true
657
+ return true;
728
658
  }
729
- ]);
659
+ });
660
+ const newParentDesc = await input({
661
+ message: 'Parent repository description:',
662
+ default: 'SpecWeave parent repository - specs, docs, and architecture'
663
+ });
664
+ const createParentOnGitHub = await confirm({
665
+ message: 'Create parent repository on GitHub?',
666
+ default: true
667
+ });
730
668
  // Merge the answers
731
- parentAnswers = { ...ownerPrompt, ...remainingAnswers };
669
+ parentAnswers = {
670
+ ...ownerPrompt,
671
+ parentName: newParentName,
672
+ description: newParentDesc,
673
+ createOnGitHub: createParentOnGitHub
674
+ };
732
675
  }
733
676
  }
734
677
  // Ask about visibility for parent repo (only if creating NEW repo on GitHub)
@@ -736,18 +679,14 @@ export class RepoStructureManager {
736
679
  if (!isLocalParent && parentAnswers.createOnGitHub) {
737
680
  // Only prompt for visibility when creating a NEW repository
738
681
  const parentVisibilityPrompt = getVisibilityPrompt(parentAnswers.parentName);
739
- const result = await inquirer.prompt([{
740
- type: 'select',
741
- name: 'parentVisibility',
742
- message: parentVisibilityPrompt.question,
743
- choices: parentVisibilityPrompt.options.map(opt => ({
744
- name: `${opt.label}\n${chalk.gray(opt.description)}`,
745
- value: opt.value,
746
- short: opt.label
747
- })),
748
- default: parentVisibilityPrompt.default
749
- }]);
750
- parentVisibility = result.parentVisibility;
682
+ parentVisibility = await select({
683
+ message: parentVisibilityPrompt.question,
684
+ choices: parentVisibilityPrompt.options.map(opt => ({
685
+ name: `${opt.label}\n${chalk.gray(opt.description)}`,
686
+ value: opt.value
687
+ })),
688
+ default: parentVisibilityPrompt.default
689
+ });
751
690
  }
752
691
  else if (!isLocalParent && parentAnswers.visibility) {
753
692
  // Use existing repository's visibility (fetched from GitHub API)
@@ -803,24 +742,22 @@ export class RepoStructureManager {
803
742
  console.log(chalk.gray('\nNext question asks for: IMPLEMENTATION repositories ONLY (not counting parent)\n'));
804
743
  }
805
744
  // Ask how many implementation repositories
806
- const promptResult = await inquirer.prompt([{
807
- type: 'number',
808
- name: 'repoCount',
809
- message: useParent
810
- ? 'šŸ“¦ How many IMPLEMENTATION repositories? (not counting parent)'
811
- : 'How many repositories?',
812
- default: hints.suggestedCount, // Use auto-detected count
813
- validate: (input) => {
814
- if (input < 1)
815
- return useParent
816
- ? 'Need at least 1 implementation repository'
817
- : 'Need at least 2 repositories';
818
- if (input > 10)
819
- return 'Maximum 10 repositories supported';
820
- return true;
821
- }
822
- }]);
823
- repoCount = promptResult.repoCount;
745
+ const repoCountAnswer = await number({
746
+ message: useParent
747
+ ? 'šŸ“¦ How many IMPLEMENTATION repositories? (not counting parent)'
748
+ : 'How many repositories?',
749
+ default: hints.suggestedCount, // Use auto-detected count
750
+ validate: (val) => {
751
+ if (val === undefined || val < 1)
752
+ return useParent
753
+ ? 'Need at least 1 implementation repository'
754
+ : 'Need at least 2 repositories';
755
+ if (val > 10)
756
+ return 'Maximum 10 repositories supported';
757
+ return true;
758
+ }
759
+ });
760
+ repoCount = repoCountAnswer ?? hints.suggestedCount;
824
761
  // Show summary AFTER for confirmation
825
762
  if (useParent && config.parentRepo) {
826
763
  if (isLocalParent) {
@@ -873,12 +810,10 @@ export class RepoStructureManager {
873
810
  console.log(chalk.green(` āœ“ Discovered: ${chalk.bold(discoveredRepo.name)}`));
874
811
  console.log(chalk.gray(` Description: ${discoveredRepo.description || '(none)'}`));
875
812
  console.log(chalk.gray(` Visibility: ${discoveredRepo.private ? 'Private' : 'Public'}`));
876
- const { confirmDiscovered } = await inquirer.prompt([{
877
- type: 'confirm',
878
- name: 'confirmDiscovered',
879
- message: 'Use this repository configuration?',
880
- default: true
881
- }]);
813
+ const confirmDiscovered = await confirm({
814
+ message: 'Use this repository configuration?',
815
+ default: true
816
+ });
882
817
  if (!confirmDiscovered) {
883
818
  // Allow manual override
884
819
  console.log(chalk.yellow(` → Switching to manual entry for this repository\n`));
@@ -904,38 +839,35 @@ export class RepoStructureManager {
904
839
  }
905
840
  }
906
841
  // Manual entry (original behavior)
907
- const repoAnswers = await inquirer.prompt([
908
- {
909
- type: 'input',
910
- name: 'name',
911
- message: 'Repository name:',
912
- default: suggestedName,
913
- validate: async (input) => {
914
- if (!input.trim())
915
- return 'Repository name is required';
916
- // Validate repository doesn't exist (skip for discovered repos)
917
- if (!isDiscovered && this.githubToken && config.parentRepo) {
918
- const result = await provider.validateRepository(config.parentRepo.owner, input, this.githubToken);
919
- if (result.exists) {
920
- return `Repository ${config.parentRepo.owner}/${input} already exists at ${result.url}`;
921
- }
842
+ const repoName = await input({
843
+ message: 'Repository name:',
844
+ default: suggestedName,
845
+ validate: async (val) => {
846
+ if (!val.trim())
847
+ return 'Repository name is required';
848
+ // Validate repository doesn't exist (skip for discovered repos)
849
+ if (!isDiscovered && this.githubToken && config.parentRepo) {
850
+ const result = await provider.validateRepository(config.parentRepo.owner, val, this.githubToken);
851
+ if (result.exists) {
852
+ return `Repository ${config.parentRepo.owner}/${val} already exists at ${result.url}`;
922
853
  }
923
- return true;
924
854
  }
925
- },
926
- {
927
- type: 'input',
928
- name: 'description',
929
- message: 'Repository description:',
930
- default: (answers) => `${path.basename(answers.name)} service`
931
- },
932
- {
933
- type: 'confirm',
934
- name: 'createOnGitHub',
935
- message: 'Create this repository on GitHub?',
936
- default: !isDiscovered // Default to true for new repos, false for discovered
855
+ return true;
937
856
  }
938
- ]);
857
+ });
858
+ const repoDescription = await input({
859
+ message: 'Repository description:',
860
+ default: `${path.basename(repoName)} service`
861
+ });
862
+ const repoCreateOnGitHub = await confirm({
863
+ message: 'Create this repository on GitHub?',
864
+ default: !isDiscovered
865
+ });
866
+ const repoAnswers = {
867
+ name: repoName,
868
+ description: repoDescription,
869
+ createOnGitHub: repoCreateOnGitHub
870
+ };
939
871
  // Smart auto-generate ID from repository name (context-aware)
940
872
  const smartId = generateRepoIdSmart(repoAnswers.name, configuredRepoNames);
941
873
  const { id: suggestedId, wasModified } = ensureUniqueId(smartId, usedIds);
@@ -945,31 +877,27 @@ export class RepoStructureManager {
945
877
  if (wasModified) {
946
878
  console.log(chalk.yellow(` āš ļø ID conflict detected: "${smartId}" already used`));
947
879
  console.log(chalk.gray(` → Suggested unique ID: "${suggestedId}"`));
948
- const { confirmId } = await inquirer.prompt([{
949
- type: 'confirm',
950
- name: 'confirmId',
951
- message: `Use "${suggestedId}" as repository ID?`,
952
- default: true
953
- }]);
954
- if (!confirmId) {
955
- const { customId } = await inquirer.prompt([{
956
- type: 'input',
957
- name: 'customId',
958
- message: 'Enter custom repository ID:',
959
- default: suggestedId,
960
- validate: (input) => {
961
- // Validate format
962
- const validation = validateRepoId(input);
963
- if (!validation.valid) {
964
- return validation.error || 'Invalid repository ID';
965
- }
966
- // Validate uniqueness
967
- if (usedIds.has(input)) {
968
- return 'Repository ID must be unique';
969
- }
970
- return true;
880
+ const confirmIdAnswer = await confirm({
881
+ message: `Use "${suggestedId}" as repository ID?`,
882
+ default: true
883
+ });
884
+ if (!confirmIdAnswer) {
885
+ const customId = await input({
886
+ message: 'Enter custom repository ID:',
887
+ default: suggestedId,
888
+ validate: (val) => {
889
+ // Validate format
890
+ const validation = validateRepoId(val);
891
+ if (!validation.valid) {
892
+ return validation.error || 'Invalid repository ID';
893
+ }
894
+ // Validate uniqueness
895
+ if (usedIds.has(val)) {
896
+ return 'Repository ID must be unique';
971
897
  }
972
- }]);
898
+ return true;
899
+ }
900
+ });
973
901
  id = customId;
974
902
  }
975
903
  }
@@ -983,18 +911,14 @@ export class RepoStructureManager {
983
911
  let visibility = 'private';
984
912
  if (repoAnswers.createOnGitHub) {
985
913
  const visibilityPrompt = getVisibilityPrompt(repoAnswers.name);
986
- const result = await inquirer.prompt([{
987
- type: 'select',
988
- name: 'visibility',
989
- message: visibilityPrompt.question,
990
- choices: visibilityPrompt.options.map(opt => ({
991
- name: `${opt.label}\n${chalk.gray(opt.description)}`,
992
- value: opt.value,
993
- short: opt.label
994
- })),
995
- default: visibilityPrompt.default
996
- }]);
997
- visibility = result.visibility;
914
+ visibility = await select({
915
+ message: visibilityPrompt.question,
916
+ choices: visibilityPrompt.options.map(opt => ({
917
+ name: `${opt.label}\n${chalk.gray(opt.description)}`,
918
+ value: opt.value
919
+ })),
920
+ default: visibilityPrompt.default
921
+ });
998
922
  }
999
923
  config.repositories.push({
1000
924
  id: id,
@@ -1044,61 +968,52 @@ export class RepoStructureManager {
1044
968
  async configureMonorepo(urlType = 'ssh', platform = 'github', provider) {
1045
969
  console.log(chalk.cyan('\nšŸ“š Monorepo Configuration\n'));
1046
970
  console.log(chalk.gray('Single repository with multiple projects/packages.\n'));
1047
- const answers = await inquirer.prompt([
1048
- {
1049
- type: 'input',
1050
- name: 'owner',
1051
- message: 'GitHub owner/organization:',
1052
- validate: (input) => !!input.trim() || 'Owner is required'
1053
- },
1054
- {
1055
- type: 'input',
1056
- name: 'repo',
1057
- message: 'Repository name:',
1058
- default: path.basename(this.projectPath),
1059
- validate: (input) => !!input.trim() || 'Repository name is required'
1060
- },
1061
- {
1062
- type: 'input',
1063
- name: 'description',
1064
- message: 'Repository description:',
1065
- default: 'Monorepo project'
1066
- },
1067
- {
1068
- type: 'input',
1069
- name: 'projects',
1070
- message: 'Project names (comma-separated, e.g., frontend,backend,shared):',
1071
- validate: (input) => {
1072
- const projects = input.split(',').map(p => p.trim()).filter(Boolean);
1073
- if (projects.length < 2) {
1074
- return 'Monorepo should have at least 2 projects';
1075
- }
1076
- return true;
971
+ const monoOwner = await input({
972
+ message: 'GitHub owner/organization:',
973
+ validate: (val) => !!val.trim() || 'Owner is required'
974
+ });
975
+ const monoRepo = await input({
976
+ message: 'Repository name:',
977
+ default: path.basename(this.projectPath),
978
+ validate: (val) => !!val.trim() || 'Repository name is required'
979
+ });
980
+ const monoDescription = await input({
981
+ message: 'Repository description:',
982
+ default: 'Monorepo project'
983
+ });
984
+ const monoProjects = await input({
985
+ message: 'Project names (comma-separated, e.g., frontend,backend,shared):',
986
+ validate: (val) => {
987
+ const projects = val.split(',').map(p => p.trim()).filter(Boolean);
988
+ if (projects.length < 2) {
989
+ return 'Monorepo should have at least 2 projects';
1077
990
  }
1078
- },
1079
- {
1080
- type: 'confirm',
1081
- name: 'createOnGitHub',
1082
- message: 'Create repository on GitHub?',
1083
- default: !existsSync(path.join(this.projectPath, '.git'))
991
+ return true;
1084
992
  }
1085
- ]);
993
+ });
994
+ const monoCreateOnGitHub = await confirm({
995
+ message: 'Create repository on GitHub?',
996
+ default: !existsSync(path.join(this.projectPath, '.git'))
997
+ });
998
+ const answers = {
999
+ owner: monoOwner,
1000
+ repo: monoRepo,
1001
+ description: monoDescription,
1002
+ projects: monoProjects,
1003
+ createOnGitHub: monoCreateOnGitHub
1004
+ };
1086
1005
  // Ask about visibility only if creating a new repository
1087
1006
  let visibility = 'private';
1088
1007
  if (answers.createOnGitHub) {
1089
1008
  const visibilityPrompt = getVisibilityPrompt(answers.repo);
1090
- const result = await inquirer.prompt([{
1091
- type: 'select',
1092
- name: 'visibility',
1093
- message: visibilityPrompt.question,
1094
- choices: visibilityPrompt.options.map(opt => ({
1095
- name: `${opt.label}\n${chalk.gray(opt.description)}`,
1096
- value: opt.value,
1097
- short: opt.label
1098
- })),
1099
- default: visibilityPrompt.default
1100
- }]);
1101
- visibility = result.visibility;
1009
+ visibility = await select({
1010
+ message: visibilityPrompt.question,
1011
+ choices: visibilityPrompt.options.map(opt => ({
1012
+ name: `${opt.label}\n${chalk.gray(opt.description)}`,
1013
+ value: opt.value
1014
+ })),
1015
+ default: visibilityPrompt.default
1016
+ });
1102
1017
  }
1103
1018
  const projects = answers.projects.split(',').map((p) => p.trim());
1104
1019
  return {