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
@@ -0,0 +1,172 @@
1
+ #!/bin/bash
2
+
3
+ # SpecWeave JIRA Sync Hook
4
+ # Runs after task completion to sync progress to JIRA Issues
5
+ #
6
+ # This hook is part of the specweave-jira plugin and handles:
7
+ # - Syncing task completion state to JIRA issues
8
+ # - Updating JIRA issue status based on increment progress
9
+ #
10
+ # Dependencies:
11
+ # - Node.js for running sync scripts
12
+ # - jq for JSON parsing
13
+ # - metadata.json must have .jira.issue field
14
+ # - JIRA API credentials in .env
15
+
16
+ set -e
17
+
18
+ # ============================================================================
19
+ # PROJECT ROOT DETECTION
20
+ # ============================================================================
21
+
22
+ # Find project root by searching upward for .specweave/ directory
23
+ find_project_root() {
24
+ local dir="$1"
25
+ while [ "$dir" != "/" ]; do
26
+ if [ -d "$dir/.specweave" ]; then
27
+ echo "$dir"
28
+ return 0
29
+ fi
30
+ dir="$(dirname "$dir")"
31
+ done
32
+ # Fallback: try current directory
33
+ if [ -d "$(pwd)/.specweave" ]; then
34
+ pwd
35
+ else
36
+ echo "$(pwd)"
37
+ fi
38
+ }
39
+
40
+ PROJECT_ROOT="$(find_project_root "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")"
41
+ cd "$PROJECT_ROOT" 2>/dev/null || true
42
+
43
+ # ============================================================================
44
+ # CONFIGURATION
45
+ # ============================================================================
46
+
47
+ LOGS_DIR=".specweave/logs"
48
+ DEBUG_LOG="$LOGS_DIR/hooks-debug.log"
49
+
50
+ mkdir -p "$LOGS_DIR" 2>/dev/null || true
51
+
52
+ # ============================================================================
53
+ # PRECONDITIONS CHECK
54
+ # ============================================================================
55
+
56
+ echo "[$(date)] [JIRA] 🔗 JIRA sync hook fired" >> "$DEBUG_LOG" 2>/dev/null || true
57
+
58
+ # Detect current increment
59
+ CURRENT_INCREMENT=$(ls -td .specweave/increments/*/ 2>/dev/null | xargs -n1 basename | grep -v "_backlog" | grep -v "_archive" | grep -v "_working" | head -1)
60
+
61
+ if [ -z "$CURRENT_INCREMENT" ]; then
62
+ echo "[$(date)] [JIRA] ℹ️ No active increment, skipping JIRA sync" >> "$DEBUG_LOG" 2>/dev/null || true
63
+ cat <<EOF
64
+ {
65
+ "continue": true
66
+ }
67
+ EOF
68
+ exit 0
69
+ fi
70
+
71
+ # Check for metadata.json
72
+ METADATA_FILE=".specweave/increments/$CURRENT_INCREMENT/metadata.json"
73
+
74
+ if [ ! -f "$METADATA_FILE" ]; then
75
+ echo "[$(date)] [JIRA] ℹ️ No metadata.json for $CURRENT_INCREMENT, skipping JIRA sync" >> "$DEBUG_LOG" 2>/dev/null || true
76
+ cat <<EOF
77
+ {
78
+ "continue": true
79
+ }
80
+ EOF
81
+ exit 0
82
+ fi
83
+
84
+ # Check for JIRA issue link
85
+ if ! command -v jq &> /dev/null; then
86
+ echo "[$(date)] [JIRA] ⚠️ jq not found, skipping JIRA sync" >> "$DEBUG_LOG" 2>/dev/null || true
87
+ cat <<EOF
88
+ {
89
+ "continue": true
90
+ }
91
+ EOF
92
+ exit 0
93
+ fi
94
+
95
+ JIRA_ISSUE=$(jq -r '.jira.issue // empty' "$METADATA_FILE" 2>/dev/null)
96
+
97
+ if [ -z "$JIRA_ISSUE" ]; then
98
+ echo "[$(date)] [JIRA] ℹ️ No JIRA issue linked to $CURRENT_INCREMENT, skipping sync" >> "$DEBUG_LOG" 2>/dev/null || true
99
+ cat <<EOF
100
+ {
101
+ "continue": true
102
+ }
103
+ EOF
104
+ exit 0
105
+ fi
106
+
107
+ # Check for Node.js
108
+ if ! command -v node &> /dev/null; then
109
+ echo "[$(date)] [JIRA] ⚠️ Node.js not found, skipping JIRA sync" >> "$DEBUG_LOG" 2>/dev/null || true
110
+ cat <<EOF
111
+ {
112
+ "continue": true
113
+ }
114
+ EOF
115
+ exit 0
116
+ fi
117
+
118
+ # Check for JIRA sync script
119
+ if [ ! -f "dist/commands/jira-sync.js" ]; then
120
+ echo "[$(date)] [JIRA] ⚠️ jira-sync.js not found, skipping JIRA sync" >> "$DEBUG_LOG" 2>/dev/null || true
121
+ cat <<EOF
122
+ {
123
+ "continue": true
124
+ }
125
+ EOF
126
+ exit 0
127
+ fi
128
+
129
+ # ============================================================================
130
+ # JIRA SYNC LOGIC
131
+ # ============================================================================
132
+
133
+ echo "[$(date)] [JIRA] 🔄 Syncing to JIRA issue $JIRA_ISSUE" >> "$DEBUG_LOG" 2>/dev/null || true
134
+
135
+ # Run JIRA sync command (non-blocking)
136
+ node dist/commands/jira-sync.js "$CURRENT_INCREMENT" 2>&1 | tee -a "$DEBUG_LOG" >/dev/null || {
137
+ echo "[$(date)] [JIRA] ⚠️ Failed to sync to JIRA (non-blocking)" >> "$DEBUG_LOG" 2>/dev/null || true
138
+ }
139
+
140
+ echo "[$(date)] [JIRA] ✅ JIRA sync complete" >> "$DEBUG_LOG" 2>/dev/null || true
141
+
142
+ # ============================================================================
143
+ # SPEC COMMIT SYNC (NEW!)
144
+ # ============================================================================
145
+
146
+ echo "[$(date)] [JIRA] 🔗 Checking for spec commit sync..." >> "$DEBUG_LOG" 2>/dev/null || true
147
+
148
+ # Call TypeScript CLI to sync commits
149
+ if command -v node &> /dev/null && [ -f "$PROJECT_ROOT/dist/cli/commands/sync-spec-commits.js" ]; then
150
+ echo "[$(date)] [JIRA] 🚀 Running spec commit sync..." >> "$DEBUG_LOG" 2>/dev/null || true
151
+
152
+ node "$PROJECT_ROOT/dist/cli/commands/sync-spec-commits.js" \
153
+ --increment "$PROJECT_ROOT/.specweave/increments/$CURRENT_INCREMENT" \
154
+ --provider jira \
155
+ 2>&1 | tee -a "$DEBUG_LOG" >/dev/null || {
156
+ echo "[$(date)] [JIRA] ⚠️ Spec commit sync failed (non-blocking)" >> "$DEBUG_LOG" 2>/dev/null || true
157
+ }
158
+
159
+ echo "[$(date)] [JIRA] ✅ Spec commit sync complete" >> "$DEBUG_LOG" 2>/dev/null || true
160
+ else
161
+ echo "[$(date)] [JIRA] ℹ️ Spec commit sync not available (node or script not found)" >> "$DEBUG_LOG" 2>/dev/null || true
162
+ fi
163
+
164
+ # ============================================================================
165
+ # OUTPUT TO CLAUDE
166
+ # ============================================================================
167
+
168
+ cat <<EOF
169
+ {
170
+ "continue": true
171
+ }
172
+ EOF
@@ -1,6 +1,6 @@
1
- import { EnhancedContentBuilder } from "../../../src/core/sync/enhanced-content-builder.js";
2
- import { SpecIncrementMapper } from "../../../src/core/sync/spec-increment-mapper.js";
3
- import { parseSpecContent } from "../../../src/core/spec-content-sync.js";
1
+ import { EnhancedContentBuilder } from "../../../dist/src/core/sync/enhanced-content-builder.js";
2
+ import { SpecIncrementMapper } from "../../../dist/src/core/sync/spec-increment-mapper.js";
3
+ import { parseSpecContent } from "../../../dist/src/core/spec-content-sync.js";
4
4
  import * as path from "path";
5
5
  import * as fs from "fs/promises";
6
6
  async function syncSpecToJiraWithEnhancedContent(options) {
@@ -1,4 +1,4 @@
1
- import inquirer from "inquirer";
1
+ import { select, checkbox, input, Separator } from "@inquirer/prompts";
2
2
  async function fetchAllJiraProjects(client) {
3
3
  console.log("\u{1F50D} Fetching Jira projects...");
4
4
  try {
@@ -31,29 +31,25 @@ async function selectJiraProjects(client, options = {}) {
31
31
  console.log("\u{1F4CB} Available Jira Projects:\n");
32
32
  console.log(` Total: ${allProjects.length} projects
33
33
  `);
34
- const { selectionMethod } = await inquirer.prompt([
35
- {
36
- type: "select",
37
- name: "selectionMethod",
38
- message: "How would you like to select projects?",
39
- choices: [
40
- {
41
- name: `\u{1F4CB} Interactive (browse and select from ${allProjects.length} projects)`,
42
- value: "interactive"
43
- },
34
+ const selectionMethod = await select({
35
+ message: "How would you like to select projects?",
36
+ choices: [
37
+ {
38
+ name: `\u{1F4CB} Interactive (browse and select from ${allProjects.length} projects)`,
39
+ value: "interactive"
40
+ },
41
+ {
42
+ name: "\u270F\uFE0F Manual entry (type project keys)",
43
+ value: "manual"
44
+ },
45
+ ...allowSelectAll ? [
44
46
  {
45
- name: "\u270F\uFE0F Manual entry (type project keys)",
46
- value: "manual"
47
- },
48
- ...allowSelectAll ? [
49
- {
50
- name: `\u2728 Select all (${allProjects.length} projects)`,
51
- value: "all"
52
- }
53
- ] : []
54
- ]
55
- }
56
- ]);
47
+ name: `\u2728 Select all (${allProjects.length} projects)`,
48
+ value: "all"
49
+ }
50
+ ] : []
51
+ ]
52
+ });
57
53
  if (selectionMethod === "all") {
58
54
  return {
59
55
  selectedKeys: allProjects.map((p) => p.key),
@@ -73,39 +69,36 @@ async function selectJiraProjects(client, options = {}) {
73
69
  }
74
70
  async function interactiveProjectSelection(allProjects, preSelected, minSelection, maxSelection, pageSize) {
75
71
  console.log("\u{1F4A1} Use <space> to select, <a> to toggle all, <i> to invert\n");
76
- const choices = allProjects.map((p) => ({
77
- name: formatProjectChoice(p),
78
- value: p.key,
79
- checked: preSelected.includes(p.key)
80
- }));
81
- choices.push(
82
- new inquirer.Separator(),
72
+ const choices = [
73
+ ...allProjects.map((p) => ({
74
+ name: formatProjectChoice(p),
75
+ value: p.key,
76
+ checked: preSelected.includes(p.key)
77
+ })),
78
+ // Add separator and manual entry option at the end
79
+ new Separator(),
83
80
  {
84
81
  name: "\u270F\uFE0F Enter project keys manually instead",
85
82
  value: "__MANUAL__",
86
83
  checked: false
87
84
  }
88
- );
89
- const { selectedKeys } = await inquirer.prompt([
90
- {
91
- type: "checkbox",
92
- name: "selectedKeys",
93
- message: `Select Jira projects (${minSelection}${maxSelection ? `-${maxSelection}` : "+"} required):`,
94
- choices,
95
- pageSize,
96
- loop: false,
97
- validate: (selected) => {
98
- const actualSelected = selected.filter((k) => k !== "__MANUAL__");
99
- if (actualSelected.length < minSelection) {
100
- return `Please select at least ${minSelection} project(s)`;
101
- }
102
- if (maxSelection && actualSelected.length > maxSelection) {
103
- return `Please select at most ${maxSelection} project(s)`;
104
- }
105
- return true;
85
+ ];
86
+ const selectedKeys = await checkbox({
87
+ message: `Select Jira projects (${minSelection}${maxSelection ? `-${maxSelection}` : "+"} required):`,
88
+ choices,
89
+ pageSize,
90
+ loop: false,
91
+ validate: (selected) => {
92
+ const actualSelected = selected.filter((k) => k !== "__MANUAL__");
93
+ if (actualSelected.length < minSelection) {
94
+ return `Please select at least ${minSelection} project(s)`;
95
+ }
96
+ if (maxSelection && actualSelected.length > maxSelection) {
97
+ return `Please select at most ${maxSelection} project(s)`;
106
98
  }
99
+ return true;
107
100
  }
108
- ]);
101
+ });
109
102
  if (selectedKeys.includes("__MANUAL__")) {
110
103
  return await manualProjectEntry(allProjects, minSelection, maxSelection);
111
104
  }
@@ -127,30 +120,26 @@ async function manualProjectEntry(allProjects, minSelection, maxSelection) {
127
120
  );
128
121
  console.log("");
129
122
  }
130
- const { manualKeys } = await inquirer.prompt([
131
- {
132
- type: "input",
133
- name: "manualKeys",
134
- message: "Project keys:",
135
- validate: (input) => {
136
- if (!input.trim()) {
137
- return "Please enter at least one project key";
138
- }
139
- const keys = input.split(",").map((k) => k.trim().toUpperCase()).filter((k) => k.length > 0);
140
- if (keys.length < minSelection) {
141
- return `Please enter at least ${minSelection} project key(s)`;
142
- }
143
- if (maxSelection && keys.length > maxSelection) {
144
- return `Please enter at most ${maxSelection} project key(s)`;
145
- }
146
- const invalidKeys = keys.filter((k) => !/^[A-Z0-9]+$/.test(k));
147
- if (invalidKeys.length > 0) {
148
- return `Invalid project key format: ${invalidKeys.join(", ")}. Use uppercase letters/numbers only.`;
149
- }
150
- return true;
123
+ const manualKeys = await input({
124
+ message: "Project keys:",
125
+ validate: (inputValue) => {
126
+ if (!inputValue.trim()) {
127
+ return "Please enter at least one project key";
128
+ }
129
+ const keys = inputValue.split(",").map((k) => k.trim().toUpperCase()).filter((k) => k.length > 0);
130
+ if (keys.length < minSelection) {
131
+ return `Please enter at least ${minSelection} project key(s)`;
132
+ }
133
+ if (maxSelection && keys.length > maxSelection) {
134
+ return `Please enter at most ${maxSelection} project key(s)`;
151
135
  }
136
+ const invalidKeys = keys.filter((k) => !/^[A-Z0-9]+$/.test(k));
137
+ if (invalidKeys.length > 0) {
138
+ return `Invalid project key format: ${invalidKeys.join(", ")}. Use uppercase letters/numbers only.`;
139
+ }
140
+ return true;
152
141
  }
153
- ]);
142
+ });
154
143
  const selectedKeys = manualKeys.split(",").map((k) => k.trim().toUpperCase()).filter((k) => k.length > 0);
155
144
  const knownKeys = allProjects.map((p) => p.key);
156
145
  const unknownKeys = selectedKeys.filter((k) => !knownKeys.includes(k));
@@ -9,7 +9,7 @@
9
9
  * - Validates project keys
10
10
  */
11
11
 
12
- import inquirer from 'inquirer';
12
+ import { select, checkbox, input, Separator } from '@inquirer/prompts';
13
13
  import { JiraClient } from '../../../src/integrations/jira/jira-client.js';
14
14
 
15
15
  // ============================================================================
@@ -101,31 +101,27 @@ export async function selectJiraProjects(
101
101
  console.log(` Total: ${allProjects.length} projects\n`);
102
102
 
103
103
  // Decide selection method
104
- const { selectionMethod } = await inquirer.prompt([
105
- {
106
- type: 'select',
107
- name: 'selectionMethod',
108
- message: 'How would you like to select projects?',
109
- choices: [
110
- {
111
- name: `📋 Interactive (browse and select from ${allProjects.length} projects)`,
112
- value: 'interactive',
113
- },
114
- {
115
- name: '✏️ Manual entry (type project keys)',
116
- value: 'manual',
117
- },
118
- ...(allowSelectAll
119
- ? [
120
- {
121
- name: `✨ Select all (${allProjects.length} projects)`,
122
- value: 'all',
123
- },
124
- ]
125
- : []),
126
- ],
127
- },
128
- ]);
104
+ const selectionMethod = await select({
105
+ message: 'How would you like to select projects?',
106
+ choices: [
107
+ {
108
+ name: `📋 Interactive (browse and select from ${allProjects.length} projects)`,
109
+ value: 'interactive' as const,
110
+ },
111
+ {
112
+ name: '✏️ Manual entry (type project keys)',
113
+ value: 'manual' as const,
114
+ },
115
+ ...(allowSelectAll
116
+ ? [
117
+ {
118
+ name: `✨ Select all (${allProjects.length} projects)`,
119
+ value: 'all' as const,
120
+ },
121
+ ]
122
+ : []),
123
+ ],
124
+ });
129
125
 
130
126
  if (selectionMethod === 'all') {
131
127
  return {
@@ -160,45 +156,40 @@ async function interactiveProjectSelection(
160
156
  ): Promise<ProjectSelectionResult> {
161
157
  console.log('💡 Use <space> to select, <a> to toggle all, <i> to invert\n');
162
158
 
163
- const choices = allProjects.map((p) => ({
164
- name: formatProjectChoice(p),
165
- value: p.key,
166
- checked: preSelected.includes(p.key),
167
- }));
168
-
169
- // Add manual entry option at the end
170
- choices.push(
171
- new inquirer.Separator(),
159
+ const choices = [
160
+ ...allProjects.map((p) => ({
161
+ name: formatProjectChoice(p),
162
+ value: p.key,
163
+ checked: preSelected.includes(p.key),
164
+ })),
165
+ // Add separator and manual entry option at the end
166
+ new Separator(),
172
167
  {
173
168
  name: '✏️ Enter project keys manually instead',
174
169
  value: '__MANUAL__',
175
170
  checked: false,
176
- } as any
177
- );
171
+ },
172
+ ];
178
173
 
179
- const { selectedKeys } = await inquirer.prompt([
180
- {
181
- type: 'checkbox',
182
- name: 'selectedKeys',
183
- message: `Select Jira projects (${minSelection}${maxSelection ? `-${maxSelection}` : '+'} required):`,
184
- choices,
185
- pageSize,
186
- loop: false,
187
- validate: (selected: string[]) => {
188
- const actualSelected = selected.filter((k) => k !== '__MANUAL__');
189
-
190
- if (actualSelected.length < minSelection) {
191
- return `Please select at least ${minSelection} project(s)`;
192
- }
193
-
194
- if (maxSelection && actualSelected.length > maxSelection) {
195
- return `Please select at most ${maxSelection} project(s)`;
196
- }
197
-
198
- return true;
199
- },
174
+ const selectedKeys = await checkbox({
175
+ message: `Select Jira projects (${minSelection}${maxSelection ? `-${maxSelection}` : '+'} required):`,
176
+ choices,
177
+ pageSize,
178
+ loop: false,
179
+ validate: (selected: readonly string[]) => {
180
+ const actualSelected = selected.filter((k) => k !== '__MANUAL__');
181
+
182
+ if (actualSelected.length < minSelection) {
183
+ return `Please select at least ${minSelection} project(s)`;
184
+ }
185
+
186
+ if (maxSelection && actualSelected.length > maxSelection) {
187
+ return `Please select at most ${maxSelection} project(s)`;
188
+ }
189
+
190
+ return true;
200
191
  },
201
- ]);
192
+ });
202
193
 
203
194
  // Check if user chose manual entry
204
195
  if (selectedKeys.includes('__MANUAL__')) {
@@ -235,39 +226,35 @@ async function manualProjectEntry(
235
226
  console.log('');
236
227
  }
237
228
 
238
- const { manualKeys } = await inquirer.prompt([
239
- {
240
- type: 'input',
241
- name: 'manualKeys',
242
- message: 'Project keys:',
243
- validate: (input: string) => {
244
- if (!input.trim()) {
245
- return 'Please enter at least one project key';
246
- }
247
-
248
- const keys = input
249
- .split(',')
250
- .map((k) => k.trim().toUpperCase())
251
- .filter((k) => k.length > 0);
252
-
253
- if (keys.length < minSelection) {
254
- return `Please enter at least ${minSelection} project key(s)`;
255
- }
256
-
257
- if (maxSelection && keys.length > maxSelection) {
258
- return `Please enter at most ${maxSelection} project key(s)`;
259
- }
260
-
261
- // Validate format (uppercase letters/numbers only)
262
- const invalidKeys = keys.filter((k) => !/^[A-Z0-9]+$/.test(k));
263
- if (invalidKeys.length > 0) {
264
- return `Invalid project key format: ${invalidKeys.join(', ')}. Use uppercase letters/numbers only.`;
265
- }
266
-
267
- return true;
268
- },
229
+ const manualKeys = await input({
230
+ message: 'Project keys:',
231
+ validate: (inputValue: string) => {
232
+ if (!inputValue.trim()) {
233
+ return 'Please enter at least one project key';
234
+ }
235
+
236
+ const keys = inputValue
237
+ .split(',')
238
+ .map((k) => k.trim().toUpperCase())
239
+ .filter((k) => k.length > 0);
240
+
241
+ if (keys.length < minSelection) {
242
+ return `Please enter at least ${minSelection} project key(s)`;
243
+ }
244
+
245
+ if (maxSelection && keys.length > maxSelection) {
246
+ return `Please enter at most ${maxSelection} project key(s)`;
247
+ }
248
+
249
+ // Validate format (uppercase letters/numbers only)
250
+ const invalidKeys = keys.filter((k) => !/^[A-Z0-9]+$/.test(k));
251
+ if (invalidKeys.length > 0) {
252
+ return `Invalid project key format: ${invalidKeys.join(', ')}. Use uppercase letters/numbers only.`;
253
+ }
254
+
255
+ return true;
269
256
  },
270
- ]);
257
+ });
271
258
 
272
259
  const selectedKeys = manualKeys
273
260
  .split(',')