specweave 0.8.17 → 0.8.19

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 (35) hide show
  1. package/CLAUDE.md +119 -27
  2. package/README.md +11 -3
  3. package/dist/cli/commands/init.d.ts.map +1 -1
  4. package/dist/cli/commands/init.js +74 -20
  5. package/dist/cli/commands/init.js.map +1 -1
  6. package/dist/cli/commands/migrate-to-profiles.js +2 -2
  7. package/dist/cli/commands/migrate-to-profiles.js.map +1 -1
  8. package/dist/cli/helpers/issue-tracker/index.d.ts.map +1 -1
  9. package/dist/cli/helpers/issue-tracker/index.js +8 -3
  10. package/dist/cli/helpers/issue-tracker/index.js.map +1 -1
  11. package/dist/cli/helpers/issue-tracker/utils.d.ts +5 -2
  12. package/dist/cli/helpers/issue-tracker/utils.d.ts.map +1 -1
  13. package/dist/cli/helpers/issue-tracker/utils.js +13 -6
  14. package/dist/cli/helpers/issue-tracker/utils.js.map +1 -1
  15. package/dist/core/sync/bidirectional-engine.d.ts +110 -0
  16. package/dist/core/sync/bidirectional-engine.d.ts.map +1 -0
  17. package/dist/core/sync/bidirectional-engine.js +356 -0
  18. package/dist/core/sync/bidirectional-engine.js.map +1 -0
  19. package/dist/utils/agents-md-compiler.js +2 -2
  20. package/dist/utils/env-multi-project-parser.d.ts +210 -0
  21. package/dist/utils/env-multi-project-parser.d.ts.map +1 -0
  22. package/dist/utils/env-multi-project-parser.js +406 -0
  23. package/dist/utils/env-multi-project-parser.js.map +1 -0
  24. package/package.json +1 -1
  25. package/plugins/specweave/hooks/post-first-increment.sh +79 -0
  26. package/plugins/specweave/skills/increment-planner/SKILL.md +50 -16
  27. package/plugins/specweave/skills/plugin-expert/SKILL.md +344 -0
  28. package/plugins/specweave/skills/specweave-framework/SKILL.md +2 -2
  29. package/plugins/specweave/skills/translator/SKILL.md +29 -0
  30. package/plugins/specweave/skills/translator/SKILL.md.bak +172 -0
  31. package/plugins/specweave-jira/lib/project-selector.ts +323 -0
  32. package/plugins/specweave-jira/lib/reorganization-detector.ts +359 -0
  33. package/plugins/specweave-jira/lib/setup-wizard.ts +256 -0
  34. package/src/templates/.gitignore.template +1 -0
  35. package/plugins/specweave-jira/lib/jira-client-v2.ts +0 -529
@@ -0,0 +1,256 @@
1
+ /**
2
+ * Smart Jira Setup Wizard
3
+ *
4
+ * Intelligent credential detection and setup flow:
5
+ * 1. Check .env for credentials (uses credentialsManager)
6
+ * 2. Interactive prompt only if missing
7
+ * 3. Never ask twice for same credentials
8
+ */
9
+
10
+ import inquirer from 'inquirer';
11
+ import { credentialsManager, JiraCredentials } from '../../../src/core/credentials-manager.js';
12
+
13
+ // ============================================================================
14
+ // Types
15
+ // ============================================================================
16
+
17
+ export { JiraCredentials } from '../../../src/core/credentials-manager.js';
18
+
19
+ export interface CredentialDetectionResult {
20
+ found: boolean;
21
+ credentials?: JiraCredentials;
22
+ source?: 'env' | 'interactive';
23
+ }
24
+
25
+ // ============================================================================
26
+ // Credential Detection
27
+ // ============================================================================
28
+
29
+ /**
30
+ * Smart credential detection - uses existing credentialsManager
31
+ */
32
+ export async function detectJiraCredentials(): Promise<CredentialDetectionResult> {
33
+ if (credentialsManager.hasJiraCredentials()) {
34
+ try {
35
+ const credentials = credentialsManager.getJiraCredentials();
36
+ console.log('āœ… Found Jira credentials in .env');
37
+ return {
38
+ found: true,
39
+ credentials,
40
+ source: 'env',
41
+ };
42
+ } catch (error) {
43
+ // Credentials exist but invalid format
44
+ return { found: false };
45
+ }
46
+ }
47
+
48
+ return { found: false };
49
+ }
50
+
51
+ // ============================================================================
52
+ // Interactive Setup
53
+ // ============================================================================
54
+
55
+ /**
56
+ * Interactive Jira credential setup
57
+ * Only runs if credentials not found
58
+ */
59
+ export async function setupJiraCredentials(): Promise<JiraCredentials> {
60
+ console.log('\nšŸ”§ Jira Setup Wizard\n');
61
+
62
+ // Check for existing credentials first
63
+ const detected = await detectJiraCredentials();
64
+
65
+ if (detected.found) {
66
+ // Ask user if they want to use existing or re-enter
67
+ const { useExisting } = await inquirer.prompt([
68
+ {
69
+ type: 'confirm',
70
+ name: 'useExisting',
71
+ message: `Found credentials in ${detected.source}. Use these credentials?`,
72
+ default: true,
73
+ },
74
+ ]);
75
+
76
+ if (useExisting) {
77
+ return detected.credentials!;
78
+ }
79
+
80
+ console.log('\nšŸ“ Enter new credentials:\n');
81
+ } else {
82
+ console.log('āš ļø No Jira credentials found\n');
83
+ console.log('šŸ“ Let\'s set up your Jira connection:\n');
84
+ }
85
+
86
+ // Interactive credential entry
87
+ const answers = await inquirer.prompt([
88
+ {
89
+ type: 'list',
90
+ name: 'setupType',
91
+ message: 'How would you like to connect to Jira?',
92
+ choices: [
93
+ {
94
+ name: 'Cloud (*.atlassian.net)',
95
+ value: 'cloud',
96
+ },
97
+ {
98
+ name: 'Server/Data Center (self-hosted)',
99
+ value: 'server',
100
+ },
101
+ ],
102
+ },
103
+ {
104
+ type: 'input',
105
+ name: 'domain',
106
+ message: (answers: any) =>
107
+ answers.setupType === 'cloud'
108
+ ? 'Jira domain (e.g., mycompany.atlassian.net):'
109
+ : 'Jira server URL (e.g., jira.mycompany.com):',
110
+ validate: (value: string) => {
111
+ if (!value) return 'Domain is required';
112
+ if (answers.setupType === 'cloud' && !value.includes('.atlassian.net')) {
113
+ return 'Cloud domain must end with .atlassian.net';
114
+ }
115
+ return true;
116
+ },
117
+ },
118
+ {
119
+ type: 'input',
120
+ name: 'email',
121
+ message: 'Email address:',
122
+ validate: (value: string) => {
123
+ if (!value) return 'Email is required';
124
+ if (!value.includes('@')) return 'Must be a valid email';
125
+ return true;
126
+ },
127
+ },
128
+ {
129
+ type: 'password',
130
+ name: 'apiToken',
131
+ message: 'API token:',
132
+ mask: '*',
133
+ validate: (value: string) => {
134
+ if (!value) return 'API token is required';
135
+ if (value.length < 10) return 'API token seems too short';
136
+ return true;
137
+ },
138
+ },
139
+ ]);
140
+
141
+ const credentials: JiraCredentials = {
142
+ domain: answers.domain,
143
+ email: answers.email,
144
+ apiToken: answers.apiToken,
145
+ };
146
+
147
+ // Test connection
148
+ console.log('\nšŸ” Testing connection...');
149
+ const isValid = await testJiraConnection(credentials);
150
+
151
+ if (!isValid) {
152
+ console.log('āŒ Failed to connect to Jira');
153
+ console.log('šŸ’” Please check your credentials and try again\n');
154
+
155
+ const { retry } = await inquirer.prompt([
156
+ {
157
+ type: 'confirm',
158
+ name: 'retry',
159
+ message: 'Would you like to try again?',
160
+ default: true,
161
+ },
162
+ ]);
163
+
164
+ if (retry) {
165
+ return setupJiraCredentials();
166
+ }
167
+
168
+ throw new Error('Jira connection failed');
169
+ }
170
+
171
+ console.log('āœ… Connection successful!\n');
172
+
173
+ // Save to .env using credentialsManager
174
+ await saveCredentialsToEnv(credentials);
175
+
176
+ return credentials;
177
+ }
178
+
179
+ /**
180
+ * Test Jira connection with credentials
181
+ */
182
+ async function testJiraConnection(credentials: JiraCredentials): Promise<boolean> {
183
+ try {
184
+ const https = await import('https');
185
+
186
+ const auth = Buffer.from(`${credentials.email}:${credentials.apiToken}`).toString('base64');
187
+
188
+ return new Promise((resolve) => {
189
+ const req = https.request(
190
+ {
191
+ hostname: credentials.domain,
192
+ path: '/rest/api/3/myself',
193
+ method: 'GET',
194
+ headers: {
195
+ Authorization: `Basic ${auth}`,
196
+ 'Content-Type': 'application/json',
197
+ },
198
+ },
199
+ (res) => {
200
+ resolve(res.statusCode === 200);
201
+ }
202
+ );
203
+
204
+ req.on('error', () => resolve(false));
205
+ req.setTimeout(5000, () => {
206
+ req.destroy();
207
+ resolve(false);
208
+ });
209
+ req.end();
210
+ });
211
+ } catch (error) {
212
+ return false;
213
+ }
214
+ }
215
+
216
+ /**
217
+ * Save credentials to .env using credentialsManager
218
+ */
219
+ async function saveCredentialsToEnv(credentials: JiraCredentials): Promise<void> {
220
+ console.log('šŸ’” Save credentials to .env for future use\n');
221
+
222
+ const { saveToEnv } = await inquirer.prompt([
223
+ {
224
+ type: 'confirm',
225
+ name: 'saveToEnv',
226
+ message: 'Save credentials to .env file?',
227
+ default: true,
228
+ },
229
+ ]);
230
+
231
+ if (saveToEnv) {
232
+ credentialsManager.saveToEnvFile({ jira: credentials });
233
+ console.log('āœ… Credentials saved to .env');
234
+ console.log('āœ… .env added to .gitignore');
235
+ } else {
236
+ console.log('āš ļø Credentials not saved. You\'ll need to enter them again next time.');
237
+ }
238
+ }
239
+
240
+ // ============================================================================
241
+ // Export Helpers
242
+ // ============================================================================
243
+
244
+ /**
245
+ * Get Jira credentials - smart detection with fallback to interactive setup
246
+ */
247
+ export async function getJiraCredentials(): Promise<JiraCredentials> {
248
+ const detected = await detectJiraCredentials();
249
+
250
+ if (detected.found) {
251
+ return detected.credentials!;
252
+ }
253
+
254
+ // Not found - run interactive setup
255
+ return setupJiraCredentials();
256
+ }
@@ -2,6 +2,7 @@
2
2
  .specweave/cache/
3
3
  .specweave/increments/*/logs/ # Gitignored, but structure preserved
4
4
  .specweave/increments/*/test-results/
5
+ .specweave/docs-site-internal/ # Generated Docusaurus site for internal docs
5
6
  .claude-plugin/ # Plugin marketplace (framework files)
6
7
  plugins/ # Plugin implementations (framework files)
7
8