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.
- package/CLAUDE.md +73 -1
- package/README.md +111 -466
- package/dist/plugins/specweave-jira/lib/setup-wizard.d.ts.map +1 -1
- package/dist/plugins/specweave-jira/lib/setup-wizard.js +57 -78
- package/dist/plugins/specweave-jira/lib/setup-wizard.js.map +1 -1
- package/dist/src/cli/commands/import-docs.d.ts.map +1 -1
- package/dist/src/cli/commands/import-docs.js +23 -31
- package/dist/src/cli/commands/import-docs.js.map +1 -1
- package/dist/src/cli/commands/import-external.d.ts.map +1 -1
- package/dist/src/cli/commands/import-external.js +6 -10
- package/dist/src/cli/commands/import-external.js.map +1 -1
- package/dist/src/cli/commands/init-multiproject.d.ts.map +1 -1
- package/dist/src/cli/commands/init-multiproject.js +58 -73
- package/dist/src/cli/commands/init-multiproject.js.map +1 -1
- package/dist/src/cli/commands/init.d.ts +17 -11
- package/dist/src/cli/commands/init.d.ts.map +1 -1
- package/dist/src/cli/commands/init.js +221 -1874
- package/dist/src/cli/commands/init.js.map +1 -1
- package/dist/src/cli/commands/install.d.ts.map +1 -1
- package/dist/src/cli/commands/install.js +14 -22
- package/dist/src/cli/commands/install.js.map +1 -1
- package/dist/src/cli/commands/migrate-config.d.ts.map +1 -1
- package/dist/src/cli/commands/migrate-config.js +6 -10
- package/dist/src/cli/commands/migrate-config.js.map +1 -1
- package/dist/src/cli/commands/switch-project.d.ts.map +1 -1
- package/dist/src/cli/commands/switch-project.js.map +1 -1
- package/dist/src/cli/helpers/ado-area-path-mapper.d.ts.map +1 -1
- package/dist/src/cli/helpers/ado-area-path-mapper.js +36 -49
- package/dist/src/cli/helpers/ado-area-path-mapper.js.map +1 -1
- package/dist/src/cli/helpers/github/increment-profile-selector.d.ts.map +1 -1
- package/dist/src/cli/helpers/github/increment-profile-selector.js.map +1 -1
- package/dist/src/cli/helpers/github/profile-manager.d.ts.map +1 -1
- package/dist/src/cli/helpers/github/profile-manager.js +8 -11
- package/dist/src/cli/helpers/github/profile-manager.js.map +1 -1
- package/dist/src/cli/helpers/github-repo-selector.d.ts.map +1 -1
- package/dist/src/cli/helpers/github-repo-selector.js +26 -50
- package/dist/src/cli/helpers/github-repo-selector.js.map +1 -1
- package/dist/src/cli/helpers/import-strategy-prompter.d.ts.map +1 -1
- package/dist/src/cli/helpers/import-strategy-prompter.js +39 -52
- package/dist/src/cli/helpers/import-strategy-prompter.js.map +1 -1
- package/dist/src/cli/helpers/init/config-detection.d.ts +40 -0
- package/dist/src/cli/helpers/init/config-detection.d.ts.map +1 -0
- package/dist/src/cli/helpers/init/config-detection.js +125 -0
- package/dist/src/cli/helpers/init/config-detection.js.map +1 -0
- package/dist/src/cli/helpers/init/directory-structure.d.ts +26 -0
- package/dist/src/cli/helpers/init/directory-structure.d.ts.map +1 -0
- package/dist/src/cli/helpers/init/directory-structure.js +190 -0
- package/dist/src/cli/helpers/init/directory-structure.js.map +1 -0
- package/dist/src/cli/helpers/init/external-import.d.ts +15 -0
- package/dist/src/cli/helpers/init/external-import.d.ts.map +1 -0
- package/dist/src/cli/helpers/init/external-import.js +251 -0
- package/dist/src/cli/helpers/init/external-import.js.map +1 -0
- package/dist/src/cli/helpers/init/index.d.ts +15 -0
- package/dist/src/cli/helpers/init/index.d.ts.map +1 -0
- package/dist/src/cli/helpers/init/index.js +26 -0
- package/dist/src/cli/helpers/init/index.js.map +1 -0
- package/dist/src/cli/helpers/init/next-steps.d.ts +15 -0
- package/dist/src/cli/helpers/init/next-steps.d.ts.map +1 -0
- package/dist/src/cli/helpers/init/next-steps.js +72 -0
- package/dist/src/cli/helpers/init/next-steps.js.map +1 -0
- package/dist/src/cli/helpers/init/path-utils.d.ts +41 -0
- package/dist/src/cli/helpers/init/path-utils.d.ts.map +1 -0
- package/dist/src/cli/helpers/init/path-utils.js +146 -0
- package/dist/src/cli/helpers/init/path-utils.js.map +1 -0
- package/dist/src/cli/helpers/init/plugin-installer.d.ts +28 -0
- package/dist/src/cli/helpers/init/plugin-installer.d.ts.map +1 -0
- package/dist/src/cli/helpers/init/plugin-installer.js +238 -0
- package/dist/src/cli/helpers/init/plugin-installer.js.map +1 -0
- package/dist/src/cli/helpers/init/repository-setup.d.ts +28 -0
- package/dist/src/cli/helpers/init/repository-setup.d.ts.map +1 -0
- package/dist/src/cli/helpers/init/repository-setup.js +78 -0
- package/dist/src/cli/helpers/init/repository-setup.js.map +1 -0
- package/dist/src/cli/helpers/init/smart-reinit.d.ts +30 -0
- package/dist/src/cli/helpers/init/smart-reinit.d.ts.map +1 -0
- package/dist/src/cli/helpers/init/smart-reinit.js +140 -0
- package/dist/src/cli/helpers/init/smart-reinit.js.map +1 -0
- package/dist/src/cli/helpers/init/testing-config.d.ts +27 -0
- package/dist/src/cli/helpers/init/testing-config.d.ts.map +1 -0
- package/dist/src/cli/helpers/init/testing-config.js +131 -0
- package/dist/src/cli/helpers/init/testing-config.js.map +1 -0
- package/dist/src/cli/helpers/init/types.d.ts +86 -0
- package/dist/src/cli/helpers/init/types.d.ts.map +1 -0
- package/dist/src/cli/helpers/init/types.js +5 -0
- package/dist/src/cli/helpers/init/types.js.map +1 -0
- package/dist/src/cli/helpers/issue-tracker/ado-auto-discover.d.ts.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/ado-auto-discover.js +10 -12
- package/dist/src/cli/helpers/issue-tracker/ado-auto-discover.js.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/ado.d.ts.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/ado.js +43 -60
- package/dist/src/cli/helpers/issue-tracker/ado.js.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/github-multi-repo.d.ts.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/github-multi-repo.js +193 -230
- package/dist/src/cli/helpers/issue-tracker/github-multi-repo.js.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/github.d.ts.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/github.js +43 -54
- package/dist/src/cli/helpers/issue-tracker/github.js.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/index.d.ts.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/index.js +27 -40
- package/dist/src/cli/helpers/issue-tracker/index.js.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/jira.d.ts.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/jira.js +54 -70
- package/dist/src/cli/helpers/issue-tracker/jira.js.map +1 -1
- package/dist/src/cli/helpers/smart-filter.d.ts.map +1 -1
- package/dist/src/cli/helpers/smart-filter.js +62 -85
- package/dist/src/cli/helpers/smart-filter.js.map +1 -1
- package/dist/src/core/increment/auto-transition-manager.d.ts +12 -0
- package/dist/src/core/increment/auto-transition-manager.d.ts.map +1 -1
- package/dist/src/core/increment/auto-transition-manager.js +45 -0
- package/dist/src/core/increment/auto-transition-manager.js.map +1 -1
- package/dist/src/core/increment/metadata-manager.d.ts.map +1 -1
- package/dist/src/core/increment/metadata-manager.js +46 -0
- package/dist/src/core/increment/metadata-manager.js.map +1 -1
- package/dist/src/core/increment/status-change-sync-trigger.d.ts +12 -0
- package/dist/src/core/increment/status-change-sync-trigger.d.ts.map +1 -1
- package/dist/src/core/increment/status-change-sync-trigger.js +48 -2
- package/dist/src/core/increment/status-change-sync-trigger.js.map +1 -1
- package/dist/src/core/living-docs/living-docs-sync.d.ts +13 -0
- package/dist/src/core/living-docs/living-docs-sync.d.ts.map +1 -1
- package/dist/src/core/living-docs/living-docs-sync.js +40 -0
- package/dist/src/core/living-docs/living-docs-sync.js.map +1 -1
- package/dist/src/core/repo-structure/repo-bulk-discovery.d.ts.map +1 -1
- package/dist/src/core/repo-structure/repo-bulk-discovery.js +63 -83
- package/dist/src/core/repo-structure/repo-bulk-discovery.js.map +1 -1
- package/dist/src/core/repo-structure/repo-structure-manager.d.ts.map +1 -1
- package/dist/src/core/repo-structure/repo-structure-manager.js +339 -424
- package/dist/src/core/repo-structure/repo-structure-manager.js.map +1 -1
- package/dist/src/core/sync/bidirectional-engine.d.ts.map +1 -1
- package/dist/src/core/sync/bidirectional-engine.js +21 -29
- package/dist/src/core/sync/bidirectional-engine.js.map +1 -1
- package/dist/src/init/InitFlow.js +15 -19
- package/dist/src/init/InitFlow.js.map +1 -1
- package/dist/src/init/repo/types.d.ts +1 -1
- package/dist/src/integrations/ado/area-path-mapper.d.ts.map +1 -1
- package/dist/src/integrations/ado/area-path-mapper.js +19 -23
- package/dist/src/integrations/ado/area-path-mapper.js.map +1 -1
- package/dist/src/utils/external-resource-validator.d.ts.map +1 -1
- package/dist/src/utils/external-resource-validator.js +41 -65
- package/dist/src/utils/external-resource-validator.js.map +1 -1
- package/dist/src/utils/project-detection.d.ts.map +1 -1
- package/dist/src/utils/project-detection.js +19 -21
- package/dist/src/utils/project-detection.js.map +1 -1
- package/dist/src/utils/project-validator.d.ts.map +1 -1
- package/dist/src/utils/project-validator.js +5 -7
- package/dist/src/utils/project-validator.js.map +1 -1
- package/package.json +2 -3
- package/plugins/specweave/agents/tech-lead/AGENT.md +9 -0
- package/plugins/specweave/hooks/docs-changed.sh.backup +79 -0
- package/plugins/specweave/hooks/human-input-required.sh.backup +75 -0
- package/plugins/specweave/hooks/post-first-increment.sh.backup +61 -0
- package/plugins/specweave/hooks/post-increment-change.sh.backup +98 -0
- package/plugins/specweave/hooks/post-increment-completion.sh.backup +231 -0
- package/plugins/specweave/hooks/post-increment-planning.sh.backup +1048 -0
- package/plugins/specweave/hooks/post-increment-status-change.sh.backup +147 -0
- package/plugins/specweave/hooks/post-spec-update.sh.backup +158 -0
- package/plugins/specweave/hooks/post-user-story-complete.sh.backup +179 -0
- package/plugins/specweave/hooks/pre-command-deduplication.sh.backup +83 -0
- package/plugins/specweave/hooks/pre-implementation.sh.backup +67 -0
- package/plugins/specweave/hooks/pre-task-completion.sh.backup +194 -0
- package/plugins/specweave/hooks/pre-tool-use.sh.backup +133 -0
- package/plugins/specweave/hooks/user-prompt-submit.sh.backup +386 -0
- package/plugins/specweave/lib/vendor/core/increment/auto-transition-manager.d.ts +12 -0
- package/plugins/specweave/lib/vendor/core/increment/auto-transition-manager.js +45 -0
- package/plugins/specweave/lib/vendor/core/increment/auto-transition-manager.js.map +1 -1
- package/plugins/specweave/lib/vendor/core/increment/metadata-manager.js +46 -0
- package/plugins/specweave/lib/vendor/core/increment/metadata-manager.js.map +1 -1
- package/plugins/specweave/skills/increment-planner/SKILL.md +10 -5
- package/plugins/specweave/skills/specweave-framework/SKILL.md +6 -4
- package/plugins/specweave/templates/coding-standards.md.template +36 -0
- package/plugins/specweave-ado/hooks/post-living-docs-update.sh.backup +353 -0
- package/plugins/specweave-ado/hooks/post-task-completion.sh.backup +172 -0
- package/plugins/specweave-ado/lib/ado-multi-project-sync.js +1 -0
- package/plugins/specweave-ado/lib/enhanced-ado-sync.js +170 -0
- package/plugins/specweave-ado/lib/project-selector.js +56 -67
- package/plugins/specweave-ado/lib/project-selector.ts +72 -85
- package/plugins/specweave-github/hooks/.specweave/logs/hooks-debug.log +1104 -0
- package/plugins/specweave-github/hooks/post-task-completion.sh.backup +258 -0
- package/plugins/specweave-github/lib/repo-selector.js +55 -66
- package/plugins/specweave-github/lib/repo-selector.ts +73 -84
- package/plugins/specweave-jira/commands/import-projects.js +3 -5
- package/plugins/specweave-jira/commands/import-projects.ts +3 -5
- package/plugins/specweave-jira/hooks/post-task-completion.sh.backup +172 -0
- package/plugins/specweave-jira/lib/enhanced-jira-sync.js +3 -3
- package/plugins/specweave-jira/lib/project-selector.js +60 -71
- package/plugins/specweave-jira/lib/project-selector.ts +78 -91
- package/plugins/specweave-jira/lib/setup-wizard.js +51 -72
- package/plugins/specweave-jira/lib/setup-wizard.ts +56 -74
- package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +1017 -0
- package/plugins/specweave-release/hooks/post-task-completion.sh.backup +110 -0
- 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
|
|
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
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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:
|
|
46
|
-
value: "
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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 =
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
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
|
|
90
|
-
{
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
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
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
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
|
|
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
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
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 =
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
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
|
-
}
|
|
177
|
-
|
|
171
|
+
},
|
|
172
|
+
];
|
|
178
173
|
|
|
179
|
-
const
|
|
180
|
-
{
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
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
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
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(',')
|