specweave 0.28.17 → 0.28.20
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/dist/plugins/specweave-ado/lib/ado-board-resolver.d.ts +94 -0
- package/dist/plugins/specweave-ado/lib/ado-board-resolver.d.ts.map +1 -0
- package/dist/plugins/specweave-ado/lib/ado-board-resolver.js +219 -0
- package/dist/plugins/specweave-ado/lib/ado-board-resolver.js.map +1 -0
- package/dist/plugins/specweave-ado/lib/ado-spec-sync.d.ts +16 -0
- package/dist/plugins/specweave-ado/lib/ado-spec-sync.d.ts.map +1 -1
- package/dist/plugins/specweave-ado/lib/ado-spec-sync.js +63 -3
- package/dist/plugins/specweave-ado/lib/ado-spec-sync.js.map +1 -1
- package/dist/plugins/specweave-ado/lib/ado-status-sync.d.ts +12 -3
- package/dist/plugins/specweave-ado/lib/ado-status-sync.d.ts.map +1 -1
- package/dist/plugins/specweave-ado/lib/ado-status-sync.js +37 -3
- package/dist/plugins/specweave-ado/lib/ado-status-sync.js.map +1 -1
- package/dist/plugins/specweave-github/lib/github-feature-sync.d.ts +6 -11
- package/dist/plugins/specweave-github/lib/github-feature-sync.d.ts.map +1 -1
- package/dist/plugins/specweave-github/lib/github-feature-sync.js +6 -11
- package/dist/plugins/specweave-github/lib/github-feature-sync.js.map +1 -1
- package/dist/plugins/specweave-github/lib/github-increment-sync-cli.d.ts +21 -0
- package/dist/plugins/specweave-github/lib/github-increment-sync-cli.d.ts.map +1 -0
- package/dist/plugins/specweave-github/lib/github-increment-sync-cli.js +445 -0
- package/dist/plugins/specweave-github/lib/github-increment-sync-cli.js.map +1 -0
- package/dist/plugins/specweave-github/lib/github-status-sync.d.ts +10 -0
- package/dist/plugins/specweave-github/lib/github-status-sync.d.ts.map +1 -1
- package/dist/plugins/specweave-github/lib/github-status-sync.js +40 -2
- package/dist/plugins/specweave-github/lib/github-status-sync.js.map +1 -1
- package/dist/plugins/specweave-github/lib/increment-issue-builder.d.ts +94 -0
- package/dist/plugins/specweave-github/lib/increment-issue-builder.d.ts.map +1 -0
- package/dist/plugins/specweave-github/lib/increment-issue-builder.js +369 -0
- package/dist/plugins/specweave-github/lib/increment-issue-builder.js.map +1 -0
- package/dist/plugins/specweave-jira/lib/jira-board-resolver.d.ts +50 -0
- package/dist/plugins/specweave-jira/lib/jira-board-resolver.d.ts.map +1 -0
- package/dist/plugins/specweave-jira/lib/jira-board-resolver.js +84 -0
- package/dist/plugins/specweave-jira/lib/jira-board-resolver.js.map +1 -0
- package/dist/plugins/specweave-jira/lib/jira-spec-sync.d.ts +12 -0
- package/dist/plugins/specweave-jira/lib/jira-spec-sync.d.ts.map +1 -1
- package/dist/plugins/specweave-jira/lib/jira-spec-sync.js +57 -5
- package/dist/plugins/specweave-jira/lib/jira-spec-sync.js.map +1 -1
- package/dist/plugins/specweave-jira/lib/jira-status-sync.d.ts +5 -1
- package/dist/plugins/specweave-jira/lib/jira-status-sync.d.ts.map +1 -1
- package/dist/plugins/specweave-jira/lib/jira-status-sync.js +12 -4
- package/dist/plugins/specweave-jira/lib/jira-status-sync.js.map +1 -1
- package/dist/src/cli/commands/import-external.d.ts.map +1 -1
- package/dist/src/cli/commands/import-external.js +12 -7
- package/dist/src/cli/commands/import-external.js.map +1 -1
- package/dist/src/cli/helpers/init/external-import.d.ts.map +1 -1
- package/dist/src/cli/helpers/init/external-import.js +308 -36
- package/dist/src/cli/helpers/init/external-import.js.map +1 -1
- package/dist/src/cli/helpers/init/jira-ado-auto-detect.d.ts +115 -0
- package/dist/src/cli/helpers/init/jira-ado-auto-detect.d.ts.map +1 -0
- package/dist/src/cli/helpers/init/jira-ado-auto-detect.js +590 -0
- package/dist/src/cli/helpers/init/jira-ado-auto-detect.js.map +1 -0
- package/dist/src/cli/helpers/issue-tracker/ado-area-selection.d.ts +65 -0
- package/dist/src/cli/helpers/issue-tracker/ado-area-selection.d.ts.map +1 -0
- package/dist/src/cli/helpers/issue-tracker/ado-area-selection.js +278 -0
- package/dist/src/cli/helpers/issue-tracker/ado-area-selection.js.map +1 -0
- package/dist/src/cli/helpers/issue-tracker/jira-board-selection.d.ts +64 -0
- package/dist/src/cli/helpers/issue-tracker/jira-board-selection.d.ts.map +1 -0
- package/dist/src/cli/helpers/issue-tracker/jira-board-selection.js +251 -0
- package/dist/src/cli/helpers/issue-tracker/jira-board-selection.js.map +1 -0
- package/dist/src/config/types.d.ts +6 -6
- package/dist/src/core/ac-test-validator-cli.js +4 -1
- package/dist/src/core/ac-test-validator-cli.js.map +1 -1
- package/dist/src/core/ac-test-validator.d.ts.map +1 -1
- package/dist/src/core/ac-test-validator.js +4 -1
- package/dist/src/core/ac-test-validator.js.map +1 -1
- package/dist/src/core/background/index.d.ts +11 -0
- package/dist/src/core/background/index.d.ts.map +1 -0
- package/dist/src/core/background/index.js +11 -0
- package/dist/src/core/background/index.js.map +1 -0
- package/dist/src/core/background/job-manager.d.ts +65 -0
- package/dist/src/core/background/job-manager.d.ts.map +1 -0
- package/dist/src/core/background/job-manager.js +192 -0
- package/dist/src/core/background/job-manager.js.map +1 -0
- package/dist/src/core/background/types.d.ts +59 -0
- package/dist/src/core/background/types.d.ts.map +1 -0
- package/dist/src/core/background/types.js +8 -0
- package/dist/src/core/background/types.js.map +1 -0
- package/dist/src/core/repo-structure/multi-repo-configurator.d.ts +25 -0
- package/dist/src/core/repo-structure/multi-repo-configurator.d.ts.map +1 -0
- package/dist/src/core/repo-structure/multi-repo-configurator.js +614 -0
- package/dist/src/core/repo-structure/multi-repo-configurator.js.map +1 -0
- package/dist/src/core/repo-structure/repo-initializer.d.ts +40 -0
- package/dist/src/core/repo-structure/repo-initializer.d.ts.map +1 -0
- package/dist/src/core/repo-structure/repo-initializer.js +252 -0
- package/dist/src/core/repo-structure/repo-initializer.js.map +1 -0
- package/dist/src/core/repo-structure/repo-structure-manager.d.ts +3 -37
- package/dist/src/core/repo-structure/repo-structure-manager.d.ts.map +1 -1
- package/dist/src/core/repo-structure/repo-structure-manager.js +23 -803
- package/dist/src/core/repo-structure/repo-structure-manager.js.map +1 -1
- package/dist/src/core/types/increment-metadata.d.ts +75 -0
- package/dist/src/core/types/increment-metadata.d.ts.map +1 -1
- package/dist/src/core/types/spec-metadata.d.ts +2 -0
- package/dist/src/core/types/spec-metadata.d.ts.map +1 -1
- package/dist/src/core/types/sync-profile.d.ts +137 -5
- package/dist/src/core/types/sync-profile.d.ts.map +1 -1
- package/dist/src/core/types/sync-profile.js +63 -0
- package/dist/src/core/types/sync-profile.js.map +1 -1
- package/dist/src/importers/external-importer.d.ts +25 -0
- package/dist/src/importers/external-importer.d.ts.map +1 -1
- package/dist/src/importers/github-importer.d.ts.map +1 -1
- package/dist/src/importers/github-importer.js +5 -3
- package/dist/src/importers/github-importer.js.map +1 -1
- package/dist/src/importers/import-coordinator.d.ts +20 -0
- package/dist/src/importers/import-coordinator.d.ts.map +1 -1
- package/dist/src/importers/import-coordinator.js.map +1 -1
- package/dist/src/importers/item-converter.d.ts +51 -0
- package/dist/src/importers/item-converter.d.ts.map +1 -1
- package/dist/src/importers/item-converter.js +39 -12
- package/dist/src/importers/item-converter.js.map +1 -1
- package/dist/src/init/architecture/types.d.ts +2 -2
- package/dist/src/init/compliance/types.d.ts +1 -1
- package/dist/src/init/repo/types.d.ts +1 -1
- package/dist/src/living-docs/fs-id-allocator.d.ts +72 -3
- package/dist/src/living-docs/fs-id-allocator.d.ts.map +1 -1
- package/dist/src/living-docs/fs-id-allocator.js +142 -16
- package/dist/src/living-docs/fs-id-allocator.js.map +1 -1
- package/dist/src/locales/de/cli.json +14 -0
- package/dist/src/locales/es/cli.json +14 -0
- package/dist/src/locales/fr/cli.json +14 -0
- package/dist/src/locales/ja/cli.json +14 -0
- package/dist/src/locales/ko/cli.json +14 -0
- package/dist/src/locales/pt/cli.json +14 -0
- package/dist/src/locales/ru/cli.json +14 -0
- package/dist/src/locales/zh/cli.json +14 -0
- package/dist/src/utils/chalk-fallback.d.ts +38 -0
- package/dist/src/utils/chalk-fallback.d.ts.map +1 -0
- package/dist/src/utils/chalk-fallback.js +118 -0
- package/dist/src/utils/chalk-fallback.js.map +1 -0
- package/dist/src/utils/project-id-generator.d.ts +127 -0
- package/dist/src/utils/project-id-generator.d.ts.map +1 -0
- package/dist/src/utils/project-id-generator.js +228 -0
- package/dist/src/utils/project-id-generator.js.map +1 -0
- package/package.json +1 -1
- package/plugins/specweave/agents/pm/AGENT.md +202 -0
- package/plugins/specweave/commands/specweave-import-external.md +5 -3
- package/plugins/specweave/commands/specweave-jobs.md +160 -0
- package/plugins/specweave/commands/specweave-sync-docs.md +6 -2
- package/plugins/specweave/hooks/pre-task-completion.sh +35 -17
- package/plugins/specweave/lib/vendor/core/ac-test-validator-cli.d.ts +16 -0
- package/plugins/specweave/lib/vendor/core/ac-test-validator-cli.js +121 -0
- package/plugins/specweave/lib/vendor/core/ac-test-validator-cli.js.map +1 -0
- package/plugins/specweave/lib/vendor/core/ac-test-validator.d.ts +111 -0
- package/plugins/specweave/lib/vendor/core/ac-test-validator.js +295 -0
- package/plugins/specweave/lib/vendor/core/ac-test-validator.js.map +1 -0
- package/plugins/specweave/lib/vendor/core/types/increment-metadata.d.ts +75 -0
- package/plugins/specweave/lib/vendor/utils/chalk-fallback.d.ts +38 -0
- package/plugins/specweave/lib/vendor/utils/chalk-fallback.js +118 -0
- package/plugins/specweave/lib/vendor/utils/chalk-fallback.js.map +1 -0
- package/plugins/specweave/lib/vendor/utils/fs-native.d.ts +179 -0
- package/plugins/specweave/lib/vendor/utils/fs-native.js +319 -0
- package/plugins/specweave/lib/vendor/utils/fs-native.js.map +1 -0
- package/plugins/specweave/skills/code-reviewer/SKILL.md +1 -1
- package/plugins/specweave/skills/docs-updater/SKILL.md +61 -0
- package/plugins/specweave/skills/increment-planner/SKILL.md +10 -335
- package/plugins/specweave/skills/increment-planner/templates/metadata.json +13 -0
- package/plugins/specweave/skills/increment-planner/templates/plan.md +50 -0
- package/plugins/specweave/skills/increment-planner/templates/spec-multi-project.md +86 -0
- package/plugins/specweave/skills/increment-planner/templates/spec-single-project.md +50 -0
- package/plugins/specweave/skills/increment-planner/templates/tasks-multi-project.md +86 -0
- package/plugins/specweave/skills/increment-planner/templates/tasks-single-project.md +48 -0
- package/plugins/specweave-ado/commands/specweave-ado-import-areas.md +358 -0
- package/plugins/specweave-ado/lib/ado-spec-sync.js +59 -3
- package/plugins/specweave-ado/lib/ado-spec-sync.ts +72 -3
- package/plugins/specweave-ado/lib/ado-status-sync.js +35 -3
- package/plugins/specweave-ado/lib/ado-status-sync.ts +48 -4
- package/plugins/specweave-alternatives/skills/architecture-alternatives/SKILL.md +1 -0
- package/plugins/specweave-alternatives/skills/bmad-method/SKILL.md +1 -0
- package/plugins/specweave-core/skills/code-quality/SKILL.md +1 -0
- package/plugins/specweave-core/skills/design-patterns/SKILL.md +1 -0
- package/plugins/specweave-core/skills/software-architecture/SKILL.md +1 -0
- package/plugins/specweave-github/commands/specweave-github-cleanup-duplicates.md +14 -10
- package/plugins/specweave-github/commands/specweave-github-sync.md +57 -0
- package/plugins/specweave-github/hooks/.specweave/logs/hooks-debug.log +74 -0
- package/plugins/specweave-github/lib/github-feature-sync.ts +6 -11
- package/plugins/specweave-github/lib/github-increment-sync-cli.js +456 -0
- package/plugins/specweave-github/lib/github-increment-sync-cli.ts +588 -0
- package/plugins/specweave-github/lib/github-status-sync.js +37 -1
- package/plugins/specweave-github/lib/github-status-sync.ts +60 -4
- package/plugins/specweave-github/lib/increment-issue-builder.js +389 -0
- package/plugins/specweave-github/lib/increment-issue-builder.ts +502 -0
- package/plugins/specweave-github/skills/github-issue-standard/SKILL.md +19 -24
- package/plugins/specweave-infrastructure/agents/observability-engineer/AGENT.md +15 -23
- package/plugins/specweave-jira/commands/specweave-jira-import-boards.md +331 -0
- package/plugins/specweave-jira/lib/jira-spec-sync.js +53 -5
- package/plugins/specweave-jira/lib/jira-spec-sync.ts +87 -7
- package/plugins/specweave-jira/lib/jira-status-sync.js +9 -3
- package/plugins/specweave-jira/lib/jira-status-sync.ts +15 -6
- package/plugins/specweave-ml/agents/data-scientist/AGENT.md +16 -20
- package/plugins/specweave-ml/agents/ml-engineer/AGENT.md +18 -19
- package/plugins/specweave-ml/skills/{ml-pipeline-workflow → mlops-dag-builder}/SKILL.md +18 -14
- package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +111 -0
- package/plugins/specweave-ui/skills/browser-automation/SKILL.md +1 -1
- package/plugins/specweave-ui/skills/ui-testing/SKILL.md +10 -122
- package/dist/plugins/specweave-github/lib/epic-content-builder.d.ts +0 -70
- package/dist/plugins/specweave-github/lib/epic-content-builder.d.ts.map +0 -1
- package/dist/plugins/specweave-github/lib/epic-content-builder.js +0 -258
- package/dist/plugins/specweave-github/lib/epic-content-builder.js.map +0 -1
- package/dist/plugins/specweave-github/lib/github-epic-sync.d.ts +0 -83
- package/dist/plugins/specweave-github/lib/github-epic-sync.d.ts.map +0 -1
- package/dist/plugins/specweave-github/lib/github-epic-sync.js +0 -466
- package/dist/plugins/specweave-github/lib/github-epic-sync.js.map +0 -1
- package/plugins/specweave-github/lib/epic-content-builder.js +0 -265
- package/plugins/specweave-github/lib/epic-content-builder.ts +0 -376
- package/plugins/specweave-github/lib/github-epic-sync.js +0 -488
- package/plugins/specweave-github/lib/github-epic-sync.ts +0 -715
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: specweave-jira:import-boards
|
|
3
|
+
description: Import JIRA boards from a project and map them to SpecWeave projects. Creates 2-level directory structure with board-based organization.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Import JIRA Boards Command
|
|
7
|
+
|
|
8
|
+
You are a JIRA integration expert. Help the user import boards from a JIRA project and map them to SpecWeave projects.
|
|
9
|
+
|
|
10
|
+
## Command Usage
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
/specweave-jira:import-boards # Interactive mode (prompts for project)
|
|
14
|
+
/specweave-jira:import-boards --project CORE # Specific JIRA project
|
|
15
|
+
/specweave-jira:import-boards --dry-run # Preview without creating directories
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Your Task
|
|
19
|
+
|
|
20
|
+
When the user runs this command:
|
|
21
|
+
|
|
22
|
+
### Step 1: Validate Prerequisites
|
|
23
|
+
|
|
24
|
+
1. **Check JIRA credentials** exist in `.env`:
|
|
25
|
+
- `JIRA_API_TOKEN`
|
|
26
|
+
- `JIRA_EMAIL`
|
|
27
|
+
- `JIRA_DOMAIN`
|
|
28
|
+
|
|
29
|
+
2. **Check config.json** for existing board mapping:
|
|
30
|
+
- If `sync.profiles.*.config.boardMapping` exists, warn user
|
|
31
|
+
|
|
32
|
+
### Step 2: Get Project Key
|
|
33
|
+
|
|
34
|
+
**If `--project` flag provided:**
|
|
35
|
+
- Use the provided project key
|
|
36
|
+
|
|
37
|
+
**If no flag (interactive mode):**
|
|
38
|
+
```
|
|
39
|
+
📋 JIRA Board Import
|
|
40
|
+
|
|
41
|
+
Enter the JIRA project key to import boards from:
|
|
42
|
+
> CORE
|
|
43
|
+
|
|
44
|
+
Fetching boards from project CORE...
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Step 3: Fetch and Display Boards
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
import { JiraClient } from '../../../src/integrations/jira/jira-client';
|
|
51
|
+
import { fetchBoardsForProject } from '../lib/jira-board-resolver';
|
|
52
|
+
|
|
53
|
+
const client = new JiraClient({
|
|
54
|
+
domain: process.env.JIRA_DOMAIN,
|
|
55
|
+
email: process.env.JIRA_EMAIL,
|
|
56
|
+
apiToken: process.env.JIRA_API_TOKEN,
|
|
57
|
+
instanceType: 'cloud'
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
const boards = await fetchBoardsForProject(client, 'CORE');
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
**Display boards:**
|
|
64
|
+
```
|
|
65
|
+
Found 5 boards in project CORE:
|
|
66
|
+
|
|
67
|
+
1. ☑ Frontend Board (Scrum, 23 active items)
|
|
68
|
+
2. ☑ Backend Board (Kanban, 45 active items)
|
|
69
|
+
3. ☑ Mobile Board (Scrum, 12 active items)
|
|
70
|
+
4. ☐ Platform Board (Kanban, 3 active items)
|
|
71
|
+
5. ☐ Archive Board (Simple, 0 items) [deselected - archive]
|
|
72
|
+
|
|
73
|
+
Select boards to import (Space to toggle, Enter to confirm)
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Step 4: Map Boards to SpecWeave Projects
|
|
77
|
+
|
|
78
|
+
For each selected board, prompt for SpecWeave project ID:
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
🏷️ Mapping boards to SpecWeave projects:
|
|
82
|
+
|
|
83
|
+
Board "Frontend Board" → SpecWeave project ID: [fe]
|
|
84
|
+
→ Keywords for auto-classification (optional): frontend, ui, react, css
|
|
85
|
+
|
|
86
|
+
Board "Backend Board" → SpecWeave project ID: [be]
|
|
87
|
+
→ Keywords for auto-classification (optional): api, server, database
|
|
88
|
+
|
|
89
|
+
Board "Mobile Board" → SpecWeave project ID: [mobile]
|
|
90
|
+
→ Keywords for auto-classification (optional): ios, android, react-native
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
**Project ID validation:**
|
|
94
|
+
- Must be lowercase, alphanumeric with hyphens
|
|
95
|
+
- Must not collide with existing project IDs
|
|
96
|
+
- If collision detected, suggest prefixed version: `core-fe` instead of `fe`
|
|
97
|
+
|
|
98
|
+
### Step 5: Create Directory Structure
|
|
99
|
+
|
|
100
|
+
Create 2-level directory structure:
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
.specweave/docs/internal/specs/
|
|
104
|
+
└── JIRA-CORE/ ← Level 1: JIRA project
|
|
105
|
+
├── fe/ ← Level 2: SpecWeave project
|
|
106
|
+
│ └── .gitkeep
|
|
107
|
+
├── be/
|
|
108
|
+
│ └── .gitkeep
|
|
109
|
+
└── mobile/
|
|
110
|
+
└── .gitkeep
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Step 6: Update config.json
|
|
114
|
+
|
|
115
|
+
Add board mapping to config:
|
|
116
|
+
|
|
117
|
+
```json
|
|
118
|
+
{
|
|
119
|
+
"sync": {
|
|
120
|
+
"profiles": {
|
|
121
|
+
"jira-default": {
|
|
122
|
+
"provider": "jira",
|
|
123
|
+
"config": {
|
|
124
|
+
"domain": "example.atlassian.net",
|
|
125
|
+
"boardMapping": {
|
|
126
|
+
"projectKey": "CORE",
|
|
127
|
+
"boards": [
|
|
128
|
+
{
|
|
129
|
+
"boardId": 123,
|
|
130
|
+
"boardName": "Frontend Board",
|
|
131
|
+
"specweaveProject": "fe",
|
|
132
|
+
"boardType": "scrum",
|
|
133
|
+
"keywords": ["frontend", "ui", "react", "css"]
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
"boardId": 456,
|
|
137
|
+
"boardName": "Backend Board",
|
|
138
|
+
"specweaveProject": "be",
|
|
139
|
+
"boardType": "kanban",
|
|
140
|
+
"keywords": ["api", "server", "database"]
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
"boardId": 789,
|
|
144
|
+
"boardName": "Mobile Board",
|
|
145
|
+
"specweaveProject": "mobile",
|
|
146
|
+
"boardType": "scrum",
|
|
147
|
+
"keywords": ["ios", "android", "react-native"]
|
|
148
|
+
}
|
|
149
|
+
]
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
"multiProject": {
|
|
156
|
+
"enabled": true,
|
|
157
|
+
"activeProject": "fe",
|
|
158
|
+
"projects": {
|
|
159
|
+
"fe": {
|
|
160
|
+
"name": "Frontend",
|
|
161
|
+
"externalTools": {
|
|
162
|
+
"jira": {
|
|
163
|
+
"boardId": 123,
|
|
164
|
+
"projectKey": "CORE"
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
},
|
|
168
|
+
"be": {
|
|
169
|
+
"name": "Backend",
|
|
170
|
+
"externalTools": {
|
|
171
|
+
"jira": {
|
|
172
|
+
"boardId": 456,
|
|
173
|
+
"projectKey": "CORE"
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
},
|
|
177
|
+
"mobile": {
|
|
178
|
+
"name": "Mobile",
|
|
179
|
+
"externalTools": {
|
|
180
|
+
"jira": {
|
|
181
|
+
"boardId": 789,
|
|
182
|
+
"projectKey": "CORE"
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Step 7: Display Summary
|
|
192
|
+
|
|
193
|
+
```
|
|
194
|
+
✅ JIRA Boards Import Complete!
|
|
195
|
+
|
|
196
|
+
📋 JIRA Project: CORE
|
|
197
|
+
📁 Created: .specweave/docs/internal/specs/JIRA-CORE/
|
|
198
|
+
|
|
199
|
+
Boards imported:
|
|
200
|
+
✓ Frontend Board (scrum) → fe
|
|
201
|
+
Keywords: frontend, ui, react, css
|
|
202
|
+
✓ Backend Board (kanban) → be
|
|
203
|
+
Keywords: api, server, database
|
|
204
|
+
✓ Mobile Board (scrum) → mobile
|
|
205
|
+
Keywords: ios, android, react-native
|
|
206
|
+
|
|
207
|
+
💡 Next steps:
|
|
208
|
+
1. Use /specweave:switch-project fe to switch active project
|
|
209
|
+
2. Create increment: /specweave:increment "feature name"
|
|
210
|
+
3. User stories will auto-sync to the correct board based on keywords
|
|
211
|
+
|
|
212
|
+
📖 Documentation: .specweave/docs/internal/architecture/adr/0143-jira-ado-multi-level-project-mapping.md
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## Examples
|
|
216
|
+
|
|
217
|
+
### Example 1: Interactive Import
|
|
218
|
+
```
|
|
219
|
+
User: /specweave-jira:import-boards
|
|
220
|
+
|
|
221
|
+
You:
|
|
222
|
+
📋 JIRA Board Import
|
|
223
|
+
|
|
224
|
+
Enter the JIRA project key: CORE
|
|
225
|
+
Fetching boards...
|
|
226
|
+
|
|
227
|
+
Found 3 boards:
|
|
228
|
+
☑ Frontend Board (scrum)
|
|
229
|
+
☑ Backend Board (kanban)
|
|
230
|
+
☐ Archive (simple) [deselected]
|
|
231
|
+
|
|
232
|
+
Mapping to SpecWeave projects:
|
|
233
|
+
Frontend Board → fe
|
|
234
|
+
Backend Board → be
|
|
235
|
+
|
|
236
|
+
✅ Import complete! 2 boards mapped.
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
### Example 2: Dry Run
|
|
240
|
+
```
|
|
241
|
+
User: /specweave-jira:import-boards --project CORE --dry-run
|
|
242
|
+
|
|
243
|
+
You:
|
|
244
|
+
📋 JIRA Board Import (DRY RUN)
|
|
245
|
+
|
|
246
|
+
Would import from project: CORE
|
|
247
|
+
|
|
248
|
+
Would create:
|
|
249
|
+
.specweave/docs/internal/specs/JIRA-CORE/
|
|
250
|
+
.specweave/docs/internal/specs/JIRA-CORE/fe/
|
|
251
|
+
.specweave/docs/internal/specs/JIRA-CORE/be/
|
|
252
|
+
|
|
253
|
+
Would update config.json with board mapping.
|
|
254
|
+
|
|
255
|
+
No changes made (dry run).
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### Example 3: Already Configured
|
|
259
|
+
```
|
|
260
|
+
User: /specweave-jira:import-boards
|
|
261
|
+
|
|
262
|
+
You:
|
|
263
|
+
⚠️ Board mapping already exists for project CORE
|
|
264
|
+
|
|
265
|
+
Current mappings:
|
|
266
|
+
Frontend Board → fe
|
|
267
|
+
Backend Board → be
|
|
268
|
+
|
|
269
|
+
Do you want to:
|
|
270
|
+
1. Add more boards
|
|
271
|
+
2. Replace existing mapping
|
|
272
|
+
3. Cancel
|
|
273
|
+
|
|
274
|
+
> 1
|
|
275
|
+
|
|
276
|
+
Fetching additional boards...
|
|
277
|
+
☐ Frontend Board (already mapped)
|
|
278
|
+
☐ Backend Board (already mapped)
|
|
279
|
+
☑ Mobile Board (new)
|
|
280
|
+
☐ Archive (deselected)
|
|
281
|
+
|
|
282
|
+
Added Mobile Board → mobile
|
|
283
|
+
|
|
284
|
+
✅ Updated! Now 3 boards mapped.
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
## Error Handling
|
|
288
|
+
|
|
289
|
+
**Missing credentials:**
|
|
290
|
+
```
|
|
291
|
+
❌ JIRA credentials not found
|
|
292
|
+
|
|
293
|
+
Please add to .env:
|
|
294
|
+
JIRA_API_TOKEN=your_token
|
|
295
|
+
JIRA_EMAIL=your_email@example.com
|
|
296
|
+
JIRA_DOMAIN=your-company.atlassian.net
|
|
297
|
+
|
|
298
|
+
Or run: specweave init . (to configure JIRA)
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
**Project not found:**
|
|
302
|
+
```
|
|
303
|
+
❌ JIRA project "INVALID" not found
|
|
304
|
+
|
|
305
|
+
Available projects you have access to:
|
|
306
|
+
- CORE (Core Development)
|
|
307
|
+
- INFRA (Infrastructure)
|
|
308
|
+
- MOBILE (Mobile Team)
|
|
309
|
+
|
|
310
|
+
Tip: Use /specweave-jira:import-boards --project CORE
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
**No boards found:**
|
|
314
|
+
```
|
|
315
|
+
⚠️ No boards found in project CORE
|
|
316
|
+
|
|
317
|
+
This could mean:
|
|
318
|
+
1. The project uses classic projects (no boards)
|
|
319
|
+
2. You don't have access to boards in this project
|
|
320
|
+
|
|
321
|
+
Suggestions:
|
|
322
|
+
- Use /specweave-jira:import-projects for project-based sync
|
|
323
|
+
- Ask your JIRA admin about board access
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
## Related Commands
|
|
327
|
+
|
|
328
|
+
- `/specweave-jira:import-projects` - Import multiple JIRA projects (not boards)
|
|
329
|
+
- `/specweave-jira:sync` - Sync increments with JIRA
|
|
330
|
+
- `/specweave:switch-project` - Switch active SpecWeave project
|
|
331
|
+
- `/specweave:init-multiproject` - Initialize multi-project mode
|
|
@@ -132,6 +132,7 @@ class JiraSpecSync {
|
|
|
132
132
|
async createJiraEpic(spec) {
|
|
133
133
|
const epicSummary = `[${spec.metadata.id.toUpperCase()}] ${spec.metadata.title}`;
|
|
134
134
|
const epicDescription = this.generateEpicDescription(spec);
|
|
135
|
+
const issueType = this.mapTypeToJira(spec.metadata.type, "Epic");
|
|
135
136
|
const payload = {
|
|
136
137
|
fields: {
|
|
137
138
|
project: {
|
|
@@ -140,9 +141,13 @@ class JiraSpecSync {
|
|
|
140
141
|
summary: epicSummary,
|
|
141
142
|
description: epicDescription,
|
|
142
143
|
issuetype: {
|
|
143
|
-
name:
|
|
144
|
+
name: issueType
|
|
144
145
|
},
|
|
145
|
-
labels: [`spec:${spec.metadata.id}`, `priority:${spec.metadata.priority}`]
|
|
146
|
+
labels: [`spec:${spec.metadata.id}`, `priority:${spec.metadata.priority}`],
|
|
147
|
+
// Set native JIRA priority field (P0→Highest, P1→High, P2→Medium, P3→Low)
|
|
148
|
+
priority: {
|
|
149
|
+
name: this.mapPriorityToJira(spec.metadata.priority)
|
|
150
|
+
}
|
|
146
151
|
}
|
|
147
152
|
};
|
|
148
153
|
const response = await this.client.post("/issue", payload);
|
|
@@ -213,7 +218,8 @@ class JiraSpecSync {
|
|
|
213
218
|
summary: storySummary,
|
|
214
219
|
description: storyDescription,
|
|
215
220
|
epicLink: epicKey,
|
|
216
|
-
labels: [`user-story`, `spec:${spec.metadata.id}`, `priority:${us.priority}`]
|
|
221
|
+
labels: [`user-story`, `spec:${spec.metadata.id}`, `priority:${us.priority}`],
|
|
222
|
+
priority: us.priority
|
|
217
223
|
});
|
|
218
224
|
created.push(us.id);
|
|
219
225
|
console.log(` \u2705 Created ${us.id} \u2192 Story ${newStory.key}`);
|
|
@@ -347,6 +353,7 @@ ${acList}
|
|
|
347
353
|
* Create Jira Story
|
|
348
354
|
*/
|
|
349
355
|
async createStory(story) {
|
|
356
|
+
const issueType = this.mapTypeToJira(story.type, "Story");
|
|
350
357
|
const payload = {
|
|
351
358
|
fields: {
|
|
352
359
|
project: {
|
|
@@ -355,12 +362,16 @@ ${acList}
|
|
|
355
362
|
summary: story.summary,
|
|
356
363
|
description: story.description,
|
|
357
364
|
issuetype: {
|
|
358
|
-
name:
|
|
365
|
+
name: issueType
|
|
359
366
|
},
|
|
360
367
|
labels: story.labels,
|
|
361
368
|
// Link to epic (field name may vary by Jira configuration)
|
|
362
|
-
customfield_10014: story.epicLink
|
|
369
|
+
customfield_10014: story.epicLink,
|
|
363
370
|
// Epic Link field (adjust if needed)
|
|
371
|
+
// Set native JIRA priority field
|
|
372
|
+
priority: {
|
|
373
|
+
name: this.mapPriorityToJira(story.priority)
|
|
374
|
+
}
|
|
364
375
|
}
|
|
365
376
|
};
|
|
366
377
|
const response = await this.client.post("/issue", payload);
|
|
@@ -411,6 +422,43 @@ ${acList}
|
|
|
411
422
|
}
|
|
412
423
|
});
|
|
413
424
|
}
|
|
425
|
+
/**
|
|
426
|
+
* Map SpecWeave priority to JIRA priority name
|
|
427
|
+
*
|
|
428
|
+
* JIRA standard priority names: Highest, High, Medium, Low, Lowest
|
|
429
|
+
*/
|
|
430
|
+
mapPriorityToJira(priority) {
|
|
431
|
+
if (!priority) return "Medium";
|
|
432
|
+
const map = {
|
|
433
|
+
P0: "Highest",
|
|
434
|
+
P1: "High",
|
|
435
|
+
P2: "Medium",
|
|
436
|
+
P3: "Low",
|
|
437
|
+
p0: "Highest",
|
|
438
|
+
p1: "High",
|
|
439
|
+
p2: "Medium",
|
|
440
|
+
p3: "Low"
|
|
441
|
+
};
|
|
442
|
+
return map[priority] || "Medium";
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* Map SpecWeave type to JIRA issue type
|
|
446
|
+
*
|
|
447
|
+
* Supports: Epic, Story, Bug, Task
|
|
448
|
+
*/
|
|
449
|
+
mapTypeToJira(type, defaultType = "Story") {
|
|
450
|
+
if (!type) return defaultType;
|
|
451
|
+
const normalizedType = type.toLowerCase();
|
|
452
|
+
const map = {
|
|
453
|
+
bug: "Bug",
|
|
454
|
+
feature: "Epic",
|
|
455
|
+
epic: "Epic",
|
|
456
|
+
story: "Story",
|
|
457
|
+
task: "Task",
|
|
458
|
+
enhancement: "Story"
|
|
459
|
+
};
|
|
460
|
+
return map[normalizedType] || defaultType;
|
|
461
|
+
}
|
|
414
462
|
}
|
|
415
463
|
export {
|
|
416
464
|
JiraSpecSync
|
|
@@ -223,7 +223,19 @@ export class JiraSpecSync {
|
|
|
223
223
|
const epicSummary = `[${spec.metadata.id.toUpperCase()}] ${spec.metadata.title}`;
|
|
224
224
|
const epicDescription = this.generateEpicDescription(spec);
|
|
225
225
|
|
|
226
|
-
|
|
226
|
+
// Determine issue type based on spec type (supports Bug for bug-type specs)
|
|
227
|
+
const issueType = this.mapTypeToJira(spec.metadata.type, 'Epic');
|
|
228
|
+
|
|
229
|
+
const payload: {
|
|
230
|
+
fields: {
|
|
231
|
+
project: { key: string };
|
|
232
|
+
summary: string;
|
|
233
|
+
description: string;
|
|
234
|
+
issuetype: { name: string };
|
|
235
|
+
labels: string[];
|
|
236
|
+
priority?: { name: string };
|
|
237
|
+
};
|
|
238
|
+
} = {
|
|
227
239
|
fields: {
|
|
228
240
|
project: {
|
|
229
241
|
key: this.config.projectKey
|
|
@@ -231,9 +243,13 @@ export class JiraSpecSync {
|
|
|
231
243
|
summary: epicSummary,
|
|
232
244
|
description: epicDescription,
|
|
233
245
|
issuetype: {
|
|
234
|
-
name:
|
|
246
|
+
name: issueType
|
|
235
247
|
},
|
|
236
|
-
labels: [`spec:${spec.metadata.id}`, `priority:${spec.metadata.priority}`]
|
|
248
|
+
labels: [`spec:${spec.metadata.id}`, `priority:${spec.metadata.priority}`],
|
|
249
|
+
// Set native JIRA priority field (P0→Highest, P1→High, P2→Medium, P3→Low)
|
|
250
|
+
priority: {
|
|
251
|
+
name: this.mapPriorityToJira(spec.metadata.priority)
|
|
252
|
+
}
|
|
237
253
|
}
|
|
238
254
|
};
|
|
239
255
|
|
|
@@ -329,7 +345,8 @@ export class JiraSpecSync {
|
|
|
329
345
|
summary: storySummary,
|
|
330
346
|
description: storyDescription,
|
|
331
347
|
epicLink: epicKey,
|
|
332
|
-
labels: [`user-story`, `spec:${spec.metadata.id}`, `priority:${us.priority}`]
|
|
348
|
+
labels: [`user-story`, `spec:${spec.metadata.id}`, `priority:${us.priority}`],
|
|
349
|
+
priority: us.priority
|
|
333
350
|
});
|
|
334
351
|
|
|
335
352
|
created.push(us.id);
|
|
@@ -497,8 +514,23 @@ ${acList}
|
|
|
497
514
|
description: string;
|
|
498
515
|
epicLink: string;
|
|
499
516
|
labels: string[];
|
|
517
|
+
priority?: string;
|
|
518
|
+
type?: string;
|
|
500
519
|
}): Promise<JiraStory> {
|
|
501
|
-
|
|
520
|
+
// Determine issue type (supports Bug for bug-type stories)
|
|
521
|
+
const issueType = this.mapTypeToJira(story.type, 'Story');
|
|
522
|
+
|
|
523
|
+
const payload: {
|
|
524
|
+
fields: {
|
|
525
|
+
project: { key: string };
|
|
526
|
+
summary: string;
|
|
527
|
+
description: string;
|
|
528
|
+
issuetype: { name: string };
|
|
529
|
+
labels: string[];
|
|
530
|
+
customfield_10014: string;
|
|
531
|
+
priority?: { name: string };
|
|
532
|
+
};
|
|
533
|
+
} = {
|
|
502
534
|
fields: {
|
|
503
535
|
project: {
|
|
504
536
|
key: this.config.projectKey
|
|
@@ -506,11 +538,15 @@ ${acList}
|
|
|
506
538
|
summary: story.summary,
|
|
507
539
|
description: story.description,
|
|
508
540
|
issuetype: {
|
|
509
|
-
name:
|
|
541
|
+
name: issueType
|
|
510
542
|
},
|
|
511
543
|
labels: story.labels,
|
|
512
544
|
// Link to epic (field name may vary by Jira configuration)
|
|
513
|
-
customfield_10014: story.epicLink // Epic Link field (adjust if needed)
|
|
545
|
+
customfield_10014: story.epicLink, // Epic Link field (adjust if needed)
|
|
546
|
+
// Set native JIRA priority field
|
|
547
|
+
priority: {
|
|
548
|
+
name: this.mapPriorityToJira(story.priority)
|
|
549
|
+
}
|
|
514
550
|
}
|
|
515
551
|
};
|
|
516
552
|
|
|
@@ -579,4 +615,48 @@ ${acList}
|
|
|
579
615
|
}
|
|
580
616
|
});
|
|
581
617
|
}
|
|
618
|
+
|
|
619
|
+
/**
|
|
620
|
+
* Map SpecWeave priority to JIRA priority name
|
|
621
|
+
*
|
|
622
|
+
* JIRA standard priority names: Highest, High, Medium, Low, Lowest
|
|
623
|
+
*/
|
|
624
|
+
private mapPriorityToJira(priority?: string): string {
|
|
625
|
+
if (!priority) return 'Medium';
|
|
626
|
+
|
|
627
|
+
const map: Record<string, string> = {
|
|
628
|
+
P0: 'Highest',
|
|
629
|
+
P1: 'High',
|
|
630
|
+
P2: 'Medium',
|
|
631
|
+
P3: 'Low',
|
|
632
|
+
p0: 'Highest',
|
|
633
|
+
p1: 'High',
|
|
634
|
+
p2: 'Medium',
|
|
635
|
+
p3: 'Low'
|
|
636
|
+
};
|
|
637
|
+
|
|
638
|
+
return map[priority] || 'Medium';
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
/**
|
|
642
|
+
* Map SpecWeave type to JIRA issue type
|
|
643
|
+
*
|
|
644
|
+
* Supports: Epic, Story, Bug, Task
|
|
645
|
+
*/
|
|
646
|
+
private mapTypeToJira(type?: string, defaultType: string = 'Story'): string {
|
|
647
|
+
if (!type) return defaultType;
|
|
648
|
+
|
|
649
|
+
const normalizedType = type.toLowerCase();
|
|
650
|
+
|
|
651
|
+
const map: Record<string, string> = {
|
|
652
|
+
bug: 'Bug',
|
|
653
|
+
feature: 'Epic',
|
|
654
|
+
epic: 'Epic',
|
|
655
|
+
story: 'Story',
|
|
656
|
+
task: 'Task',
|
|
657
|
+
enhancement: 'Story'
|
|
658
|
+
};
|
|
659
|
+
|
|
660
|
+
return map[normalizedType] || defaultType;
|
|
661
|
+
}
|
|
582
662
|
}
|
|
@@ -33,25 +33,31 @@ class JiraStatusSync {
|
|
|
33
33
|
* JIRA requires using transitions to change status.
|
|
34
34
|
* Cannot directly set status field.
|
|
35
35
|
*
|
|
36
|
+
* Handles missing transitions gracefully by logging a warning
|
|
37
|
+
* instead of throwing an error.
|
|
38
|
+
*
|
|
36
39
|
* @param issueKey - JIRA issue key (e.g., PROJ-123)
|
|
37
40
|
* @param status - Desired status
|
|
41
|
+
* @returns true if transition succeeded, false if not available
|
|
38
42
|
*/
|
|
39
43
|
async updateStatus(issueKey, status) {
|
|
40
44
|
const transitionsResponse = await this.client.get(`/issue/${issueKey}/transitions`);
|
|
41
45
|
const transitions = transitionsResponse.data.transitions;
|
|
42
46
|
const targetTransition = transitions.find(
|
|
43
|
-
(t) => t.to.name === status.state
|
|
47
|
+
(t) => t.to.name.toLowerCase() === status.state.toLowerCase()
|
|
44
48
|
);
|
|
45
49
|
if (!targetTransition) {
|
|
46
|
-
|
|
47
|
-
|
|
50
|
+
console.warn(
|
|
51
|
+
`\u26A0\uFE0F Cannot transition ${issueKey} to "${status.state}". Available transitions: ${transitions.map((t) => t.to.name).join(", ")}. This may be expected if your JIRA workflow doesn't support this status.`
|
|
48
52
|
);
|
|
53
|
+
return false;
|
|
49
54
|
}
|
|
50
55
|
await this.client.post(`/issue/${issueKey}/transitions`, {
|
|
51
56
|
transition: {
|
|
52
57
|
id: targetTransition.id
|
|
53
58
|
}
|
|
54
59
|
});
|
|
60
|
+
return true;
|
|
55
61
|
}
|
|
56
62
|
/**
|
|
57
63
|
* Post comment about status change to JIRA issue
|
|
@@ -85,24 +85,31 @@ export class JiraStatusSync {
|
|
|
85
85
|
* JIRA requires using transitions to change status.
|
|
86
86
|
* Cannot directly set status field.
|
|
87
87
|
*
|
|
88
|
+
* Handles missing transitions gracefully by logging a warning
|
|
89
|
+
* instead of throwing an error.
|
|
90
|
+
*
|
|
88
91
|
* @param issueKey - JIRA issue key (e.g., PROJ-123)
|
|
89
92
|
* @param status - Desired status
|
|
93
|
+
* @returns true if transition succeeded, false if not available
|
|
90
94
|
*/
|
|
91
|
-
async updateStatus(issueKey: string, status: ExternalStatus): Promise<
|
|
95
|
+
async updateStatus(issueKey: string, status: ExternalStatus): Promise<boolean> {
|
|
92
96
|
// 1. Get available transitions for this issue
|
|
93
97
|
const transitionsResponse = await this.client.get(`/issue/${issueKey}/transitions`);
|
|
94
98
|
const transitions: JiraTransition[] = transitionsResponse.data.transitions;
|
|
95
99
|
|
|
96
|
-
// 2. Find transition that leads to desired status
|
|
100
|
+
// 2. Find transition that leads to desired status (case-insensitive)
|
|
97
101
|
const targetTransition = transitions.find(
|
|
98
|
-
(t) => t.to.name === status.state
|
|
102
|
+
(t) => t.to.name.toLowerCase() === status.state.toLowerCase()
|
|
99
103
|
);
|
|
100
104
|
|
|
101
105
|
if (!targetTransition) {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
106
|
+
// Log warning instead of throwing - workflow may not support this transition
|
|
107
|
+
console.warn(
|
|
108
|
+
`⚠️ Cannot transition ${issueKey} to "${status.state}". ` +
|
|
109
|
+
`Available transitions: ${transitions.map(t => t.to.name).join(', ')}. ` +
|
|
110
|
+
`This may be expected if your JIRA workflow doesn't support this status.`
|
|
105
111
|
);
|
|
112
|
+
return false;
|
|
106
113
|
}
|
|
107
114
|
|
|
108
115
|
// 3. Execute transition
|
|
@@ -111,6 +118,8 @@ export class JiraStatusSync {
|
|
|
111
118
|
id: targetTransition.id
|
|
112
119
|
}
|
|
113
120
|
});
|
|
121
|
+
|
|
122
|
+
return true;
|
|
114
123
|
}
|
|
115
124
|
|
|
116
125
|
/**
|