specweave 0.22.14 ā 0.23.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 +178 -1
- package/dist/src/cli/commands/import-external.d.ts +22 -0
- package/dist/src/cli/commands/import-external.d.ts.map +1 -0
- package/dist/src/cli/commands/import-external.js +282 -0
- package/dist/src/cli/commands/import-external.js.map +1 -0
- package/dist/src/cli/commands/init.d.ts.map +1 -1
- package/dist/src/cli/commands/init.js +46 -0
- package/dist/src/cli/commands/init.js.map +1 -1
- package/dist/src/cli/helpers/github-repo-selector.d.ts +59 -0
- package/dist/src/cli/helpers/github-repo-selector.d.ts.map +1 -0
- package/dist/src/cli/helpers/github-repo-selector.js +265 -0
- package/dist/src/cli/helpers/github-repo-selector.js.map +1 -0
- package/dist/src/config/types.d.ts +16 -16
- package/dist/src/core/increment/ac-status-manager.d.ts.map +1 -1
- package/dist/src/core/increment/ac-status-manager.js +4 -2
- package/dist/src/core/increment/ac-status-manager.js.map +1 -1
- package/dist/src/core/increment/completion-validator.d.ts +30 -1
- package/dist/src/core/increment/completion-validator.d.ts.map +1 -1
- package/dist/src/core/increment/completion-validator.js +151 -3
- package/dist/src/core/increment/completion-validator.js.map +1 -1
- package/dist/src/core/increment/increment-archiver.d.ts +25 -0
- package/dist/src/core/increment/increment-archiver.d.ts.map +1 -1
- package/dist/src/core/increment/increment-archiver.js +130 -3
- package/dist/src/core/increment/increment-archiver.js.map +1 -1
- package/dist/src/core/living-docs/feature-archiver.d.ts +37 -0
- package/dist/src/core/living-docs/feature-archiver.d.ts.map +1 -1
- package/dist/src/core/living-docs/feature-archiver.js +262 -18
- package/dist/src/core/living-docs/feature-archiver.js.map +1 -1
- package/dist/src/core/living-docs/feature-id-manager.d.ts +17 -0
- package/dist/src/core/living-docs/feature-id-manager.d.ts.map +1 -1
- package/dist/src/core/living-docs/feature-id-manager.js +25 -0
- package/dist/src/core/living-docs/feature-id-manager.js.map +1 -1
- package/dist/src/core/living-docs/living-docs-sync.d.ts +14 -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 +46 -0
- package/dist/src/core/living-docs/living-docs-sync.js.map +1 -1
- package/dist/src/core/sync/sync-event-logger.d.ts +15 -1
- package/dist/src/core/sync/sync-event-logger.d.ts.map +1 -1
- package/dist/src/core/sync/sync-event-logger.js +39 -1
- package/dist/src/core/sync/sync-event-logger.js.map +1 -1
- package/dist/src/core/types/sync-config-validator.d.ts +57 -0
- package/dist/src/core/types/sync-config-validator.d.ts.map +1 -0
- package/dist/src/core/types/sync-config-validator.js +116 -0
- package/dist/src/core/types/sync-config-validator.js.map +1 -0
- package/dist/src/importers/duplicate-detector.d.ts +107 -0
- package/dist/src/importers/duplicate-detector.d.ts.map +1 -0
- package/dist/src/importers/duplicate-detector.js +189 -0
- package/dist/src/importers/duplicate-detector.js.map +1 -0
- package/dist/src/importers/import-coordinator.d.ts +15 -0
- package/dist/src/importers/import-coordinator.d.ts.map +1 -1
- package/dist/src/importers/import-coordinator.js +43 -1
- package/dist/src/importers/import-coordinator.js.map +1 -1
- package/dist/src/importers/item-converter.d.ts +5 -0
- package/dist/src/importers/item-converter.d.ts.map +1 -1
- package/dist/src/importers/item-converter.js +27 -2
- package/dist/src/importers/item-converter.js.map +1 -1
- package/dist/src/importers/rate-limiter.d.ts +128 -0
- package/dist/src/importers/rate-limiter.d.ts.map +1 -0
- package/dist/src/importers/rate-limiter.js +200 -0
- package/dist/src/importers/rate-limiter.js.map +1 -0
- package/dist/src/init/compliance/types.d.ts +2 -2
- package/dist/src/integrations/ado/ado-client.d.ts +6 -0
- package/dist/src/integrations/ado/ado-client.d.ts.map +1 -1
- package/dist/src/integrations/ado/ado-client.js +23 -0
- package/dist/src/integrations/ado/ado-client.js.map +1 -1
- package/dist/src/integrations/jira/jira-client.d.ts +6 -0
- package/dist/src/integrations/jira/jira-client.d.ts.map +1 -1
- package/dist/src/integrations/jira/jira-client.js +38 -0
- package/dist/src/integrations/jira/jira-client.js.map +1 -1
- package/dist/src/sync/external-item-sync-service.d.ts +150 -0
- package/dist/src/sync/external-item-sync-service.d.ts.map +1 -0
- package/dist/src/sync/external-item-sync-service.js +241 -0
- package/dist/src/sync/external-item-sync-service.js.map +1 -0
- package/dist/src/sync/format-preservation-sync.d.ts +90 -0
- package/dist/src/sync/format-preservation-sync.d.ts.map +1 -0
- package/dist/src/sync/format-preservation-sync.js +173 -0
- package/dist/src/sync/format-preservation-sync.js.map +1 -0
- package/dist/src/sync/index.d.ts +8 -0
- package/dist/src/sync/index.d.ts.map +1 -0
- package/dist/src/sync/index.js +6 -0
- package/dist/src/sync/index.js.map +1 -0
- package/dist/src/sync/sync-coordinator.d.ts +49 -0
- package/dist/src/sync/sync-coordinator.d.ts.map +1 -0
- package/dist/src/sync/sync-coordinator.js +248 -0
- package/dist/src/sync/sync-coordinator.js.map +1 -0
- package/dist/src/sync/sync-metadata.d.ts +75 -0
- package/dist/src/sync/sync-metadata.d.ts.map +1 -0
- package/dist/src/sync/sync-metadata.js +100 -0
- package/dist/src/sync/sync-metadata.js.map +1 -0
- package/dist/src/types/living-docs-us-file.d.ts +63 -0
- package/dist/src/types/living-docs-us-file.d.ts.map +1 -0
- package/dist/src/types/living-docs-us-file.js +27 -0
- package/dist/src/types/living-docs-us-file.js.map +1 -0
- package/dist/src/validators/format-preservation-validator.d.ts +127 -0
- package/dist/src/validators/format-preservation-validator.d.ts.map +1 -0
- package/dist/src/validators/format-preservation-validator.js +187 -0
- package/dist/src/validators/format-preservation-validator.js.map +1 -0
- package/package.json +3 -2
- package/plugins/specweave/.claude-plugin/plugin.json +20 -0
- package/plugins/specweave/commands/specweave-archive-features.md +11 -1
- package/plugins/specweave/commands/specweave-import-docs.md +88 -278
- package/plugins/specweave/commands/specweave-import-external.md +407 -0
- package/plugins/specweave/hooks/post-edit-spec.sh +41 -0
- package/plugins/specweave/hooks/post-increment-completion.sh +0 -0
- package/plugins/specweave/hooks/post-spec-update.sh +0 -0
- package/plugins/specweave/hooks/post-task-completion.sh +13 -3
- package/plugins/specweave/hooks/post-write-spec.sh +37 -0
- package/plugins/specweave/lib/hooks/auto-transition.js +1 -1
- package/plugins/specweave/lib/hooks/auto-transition.ts +1 -1
- package/plugins/specweave/lib/hooks/invoke-translator-skill.js +1 -1
- package/plugins/specweave/lib/hooks/invoke-translator-skill.ts +1 -1
- package/plugins/specweave/lib/hooks/sync-living-docs.js +35 -1
- package/plugins/specweave/lib/hooks/sync-us-tasks.js +179 -3
- package/plugins/specweave/lib/hooks/translate-file.js +1 -1
- package/plugins/specweave/lib/hooks/translate-file.ts +1 -1
- package/plugins/specweave/lib/hooks/update-ac-status.js +1 -1
- package/plugins/specweave/lib/hooks/update-ac-status.ts +1 -1
- package/plugins/specweave/lib/vendor/core/increment/ac-status-manager.d.ts +115 -0
- package/plugins/specweave/lib/vendor/core/increment/ac-status-manager.js +345 -0
- package/plugins/specweave/lib/vendor/core/increment/ac-status-manager.js.map +1 -0
- package/plugins/specweave/lib/vendor/core/increment/active-increment-manager.d.ts +106 -0
- package/plugins/specweave/lib/vendor/core/increment/active-increment-manager.js +220 -0
- package/plugins/specweave/lib/vendor/core/increment/active-increment-manager.js.map +1 -0
- package/plugins/specweave/lib/vendor/core/increment/auto-transition-manager.d.ts +60 -0
- package/plugins/specweave/lib/vendor/core/increment/auto-transition-manager.js +192 -0
- package/plugins/specweave/lib/vendor/core/increment/auto-transition-manager.js.map +1 -0
- package/plugins/specweave/lib/vendor/core/increment/duplicate-detector.d.ts +52 -0
- package/plugins/specweave/lib/vendor/core/increment/duplicate-detector.js +276 -0
- package/plugins/specweave/lib/vendor/core/increment/duplicate-detector.js.map +1 -0
- package/plugins/specweave/lib/vendor/core/increment/metadata-manager.d.ts +163 -0
- package/plugins/specweave/lib/vendor/core/increment/metadata-manager.js +541 -0
- package/plugins/specweave/lib/vendor/core/increment/metadata-manager.js.map +1 -0
- package/plugins/specweave/lib/vendor/core/types/increment-metadata.d.ts +157 -0
- package/plugins/specweave/lib/vendor/core/types/increment-metadata.js +191 -0
- package/plugins/specweave/lib/vendor/core/types/increment-metadata.js.map +1 -0
- package/plugins/specweave/lib/vendor/generators/spec/task-parser.d.ts +95 -0
- package/plugins/specweave/lib/vendor/generators/spec/task-parser.js +301 -0
- package/plugins/specweave/lib/vendor/generators/spec/task-parser.js.map +1 -0
- package/plugins/specweave/lib/vendor/utils/logger.d.ts +48 -0
- package/plugins/specweave/lib/vendor/utils/logger.js +53 -0
- package/plugins/specweave/lib/vendor/utils/logger.js.map +1 -0
- package/plugins/specweave/lib/vendor/utils/translation.d.ts +187 -0
- package/plugins/specweave/lib/vendor/utils/translation.js +414 -0
- package/plugins/specweave/lib/vendor/utils/translation.js.map +1 -0
- package/plugins/specweave-ado/lib/ado-multi-project-sync.js +0 -1
- package/plugins/specweave-github/commands/specweave-github-update-user-story.md +1 -1
- package/plugins/specweave-github/skills/github-issue-standard/SKILL.md +1 -1
- package/plugins/specweave-jira/lib/enhanced-jira-sync.js +3 -3
- package/plugins/specweave-ado/lib/enhanced-ado-sync.js +0 -170
- package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +0 -5694
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: specweave:import-external
|
|
3
|
+
description: Manually pull external work items from GitHub, JIRA, or Azure DevOps into living docs. Supports time range filtering, platform selection, and dry-run mode for ongoing imports after initial setup.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Import External Work Items
|
|
7
|
+
|
|
8
|
+
Import work items from GitHub (issues/milestones), JIRA (epics/stories), or Azure DevOps (work items) into SpecWeave living docs.
|
|
9
|
+
|
|
10
|
+
## What This Does
|
|
11
|
+
|
|
12
|
+
1. **Detects configured external tools** (GitHub, JIRA, ADO) from environment/config
|
|
13
|
+
2. **Fetches work items** based on time range filter (since last import by default)
|
|
14
|
+
3. **Assigns IDs** with E suffix (US-001E, T-001E) to indicate external origin
|
|
15
|
+
4. **Creates living docs files** in `.specweave/docs/internal/specs/FS-XXXE/`
|
|
16
|
+
5. **Updates sync metadata** (`.specweave/sync-metadata.json`) with import timestamp
|
|
17
|
+
6. **Skips duplicates** automatically (checks existing external IDs)
|
|
18
|
+
7. **Shows progress** indicator and summary report
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
/specweave:import-external [options]
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Options
|
|
27
|
+
|
|
28
|
+
- `--since=<range>` - Time range filter (default: since last import)
|
|
29
|
+
- `last` - Since last import (uses sync metadata)
|
|
30
|
+
- `1m`, `3m`, `6m` - Last 1/3/6 months
|
|
31
|
+
- `all` - All items (no time filter)
|
|
32
|
+
- Custom: `2025-01-01` - Since specific date (ISO format)
|
|
33
|
+
- `--github-only` - Import from GitHub only
|
|
34
|
+
- `--jira-only` - Import from JIRA only
|
|
35
|
+
- `--ado-only` - Import from Azure DevOps only
|
|
36
|
+
- `--dry-run` - Preview what would be imported without creating files
|
|
37
|
+
|
|
38
|
+
## Examples
|
|
39
|
+
|
|
40
|
+
### Example 1: Import New Items (Default)
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
/specweave:import-external
|
|
44
|
+
|
|
45
|
+
# Uses default behavior:
|
|
46
|
+
# - Imports from ALL configured platforms (GitHub, JIRA, ADO)
|
|
47
|
+
# - Since last import timestamp (from .specweave/sync-metadata.json)
|
|
48
|
+
# - Creates living docs files
|
|
49
|
+
# - Updates sync metadata
|
|
50
|
+
|
|
51
|
+
# Result:
|
|
52
|
+
# š Importing from GitHub... [30/30] ā
|
|
53
|
+
# š Importing from JIRA... [12/12] ā
|
|
54
|
+
# š Import Summary:
|
|
55
|
+
# Total imported: 42 items
|
|
56
|
+
# - GitHub: 30 items (US-201E to US-230E)
|
|
57
|
+
# - JIRA: 12 items (US-231E to US-242E)
|
|
58
|
+
# Duplicates skipped: 5 items
|
|
59
|
+
# ā
Import complete!
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Example 2: GitHub Only (Last 3 Months)
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
/specweave:import-external --github-only --since=3m
|
|
66
|
+
|
|
67
|
+
# Imports only from GitHub
|
|
68
|
+
# Items created in last 3 months
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Example 3: Dry Run (Preview)
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
/specweave:import-external --dry-run --since=1m
|
|
75
|
+
|
|
76
|
+
# Shows what would be imported without creating files
|
|
77
|
+
# Useful for checking item counts before actual import
|
|
78
|
+
|
|
79
|
+
# Result:
|
|
80
|
+
# š Dry run - no files will be created
|
|
81
|
+
# š Preview:
|
|
82
|
+
# GitHub: 25 items (5 duplicates skipped)
|
|
83
|
+
# JIRA: 10 items (2 duplicates skipped)
|
|
84
|
+
# Total: 35 new items, 7 existing
|
|
85
|
+
# ā ļø Remove --dry-run to perform actual import
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Example 4: JIRA Only (All Items)
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
/specweave:import-external --jira-only --since=all
|
|
92
|
+
|
|
93
|
+
# Imports all JIRA items (no time filter)
|
|
94
|
+
# ā ļø Warning shown if > 100 items detected
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Time Range Filters
|
|
98
|
+
|
|
99
|
+
### Since Last Import (Default)
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
/specweave:import-external
|
|
103
|
+
|
|
104
|
+
# Reads last import timestamp from:
|
|
105
|
+
# .specweave/sync-metadata.json
|
|
106
|
+
# {
|
|
107
|
+
# "github": { "lastImport": "2025-11-15T10:30:00Z" },
|
|
108
|
+
# "jira": { "lastImport": "2025-11-10T14:20:00Z" }
|
|
109
|
+
# }
|
|
110
|
+
#
|
|
111
|
+
# GitHub: imports items created after 2025-11-15T10:30:00Z
|
|
112
|
+
# JIRA: imports items created after 2025-11-10T14:20:00Z
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Relative Time Ranges
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
--since=1m # Last 1 month
|
|
119
|
+
--since=3m # Last 3 months
|
|
120
|
+
--since=6m # Last 6 months
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Absolute Date
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
--since=2025-01-01 # Since January 1, 2025 (ISO format: YYYY-MM-DD)
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### All Items
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
--since=all # Import all items (no time filter)
|
|
133
|
+
# ā ļø Warning: May import hundreds of items
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## Configured Platforms
|
|
137
|
+
|
|
138
|
+
The command auto-detects configured platforms from:
|
|
139
|
+
|
|
140
|
+
### GitHub
|
|
141
|
+
- **Detection**: `.git/config` remote URL
|
|
142
|
+
- **Auth**: `GITHUB_TOKEN` environment variable
|
|
143
|
+
- **Format**: `github.com/{owner}/{repo}`
|
|
144
|
+
|
|
145
|
+
### JIRA
|
|
146
|
+
- **Detection**: `JIRA_HOST` environment variable
|
|
147
|
+
- **Auth**: `JIRA_EMAIL` + `JIRA_API_TOKEN`
|
|
148
|
+
- **Format**: `https://{company}.atlassian.net`
|
|
149
|
+
|
|
150
|
+
### Azure DevOps
|
|
151
|
+
- **Detection**: `ADO_ORG_URL` environment variable
|
|
152
|
+
- **Auth**: `ADO_PAT` (Personal Access Token)
|
|
153
|
+
- **Format**: `https://dev.azure.com/{org}` + `ADO_PROJECT`
|
|
154
|
+
|
|
155
|
+
## Progress Indicator
|
|
156
|
+
|
|
157
|
+
During import, you'll see real-time progress:
|
|
158
|
+
|
|
159
|
+
```
|
|
160
|
+
š Importing from GitHub... [25/150] ā
|
|
161
|
+
ā ļø GitHub rate limit low: 42/5000 remaining. Resets at 10:45 AM (in 300s).
|
|
162
|
+
š Importing from GitHub... [150/150] ā
|
|
163
|
+
|
|
164
|
+
š Importing from JIRA... [12/12] ā
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
- **Spinner**: Shows active import
|
|
168
|
+
- **Counter**: `[current/total]` items processed
|
|
169
|
+
- **Rate limit warnings**: Shown if remaining requests drop below threshold
|
|
170
|
+
- **Checkmark**: `ā` when platform import completes
|
|
171
|
+
|
|
172
|
+
## Summary Report
|
|
173
|
+
|
|
174
|
+
After import, a detailed summary is shown:
|
|
175
|
+
|
|
176
|
+
```
|
|
177
|
+
š Import Summary:
|
|
178
|
+
Total imported: 162 items
|
|
179
|
+
- GitHub: 150 items (US-201E to US-350E)
|
|
180
|
+
- JIRA: 12 items (US-351E to US-362E)
|
|
181
|
+
|
|
182
|
+
Duplicates skipped: 8 items
|
|
183
|
+
- GitHub: 5 items (already imported)
|
|
184
|
+
- JIRA: 3 items (already imported)
|
|
185
|
+
|
|
186
|
+
Rate limit status:
|
|
187
|
+
- GitHub: 3842/5000 remaining (resets at 11:00 AM)
|
|
188
|
+
- JIRA: Estimated 950/1000 remaining
|
|
189
|
+
|
|
190
|
+
ā
Import complete!
|
|
191
|
+
Living docs updated: .specweave/docs/internal/specs/
|
|
192
|
+
Sync metadata updated: .specweave/sync-metadata.json
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
## Duplicate Detection
|
|
196
|
+
|
|
197
|
+
The command automatically skips items that have already been imported:
|
|
198
|
+
|
|
199
|
+
- Scans all `us-*.md` files in living docs
|
|
200
|
+
- Checks `external_id` frontmatter field
|
|
201
|
+
- Skips if external ID already exists (e.g., `GH-#638`, `JIRA-PROJ-123`)
|
|
202
|
+
- Reports skipped count in summary
|
|
203
|
+
|
|
204
|
+
## Rate Limiting
|
|
205
|
+
|
|
206
|
+
The command monitors API rate limits and handles them gracefully:
|
|
207
|
+
|
|
208
|
+
### Warning Threshold (100 requests remaining)
|
|
209
|
+
|
|
210
|
+
```
|
|
211
|
+
ā ļø GitHub rate limit low: 42/5000 remaining. Resets at 10:45 AM (in 300s).
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
- Import continues normally
|
|
215
|
+
- Warning shown to user
|
|
216
|
+
|
|
217
|
+
### Pause Threshold (10 requests remaining)
|
|
218
|
+
|
|
219
|
+
```
|
|
220
|
+
ā ļø GitHub rate limit critically low. Waiting 60s before continuing...
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
- Import pauses automatically
|
|
224
|
+
- Resumes after wait period
|
|
225
|
+
- No user action required
|
|
226
|
+
|
|
227
|
+
### Retry Suggestions (Rate limit exceeded)
|
|
228
|
+
|
|
229
|
+
```
|
|
230
|
+
ā GitHub rate limit exceeded.
|
|
231
|
+
Remaining: 0/5000
|
|
232
|
+
Resets at: 10:45 AM (in 300 seconds)
|
|
233
|
+
|
|
234
|
+
š” Suggestions:
|
|
235
|
+
- Wait 5 minutes and retry
|
|
236
|
+
- Use --github-only next time to avoid hitting limit
|
|
237
|
+
- Increase time range to reduce item count (--since=1m instead of --since=all)
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
## Large Import Confirmation
|
|
241
|
+
|
|
242
|
+
If import detects > 100 items, you'll be prompted:
|
|
243
|
+
|
|
244
|
+
```
|
|
245
|
+
ā ļø Found 250 items to import:
|
|
246
|
+
- GitHub: 200 items
|
|
247
|
+
- JIRA: 50 items
|
|
248
|
+
|
|
249
|
+
This may take 5-10 minutes and use significant API quota.
|
|
250
|
+
|
|
251
|
+
Continue? (Y/n) _
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
- Press `Y` or `Enter` to proceed
|
|
255
|
+
- Press `n` to cancel
|
|
256
|
+
- Use `--since=1m` to reduce item count
|
|
257
|
+
|
|
258
|
+
## Sync Metadata
|
|
259
|
+
|
|
260
|
+
After successful import, sync metadata is updated:
|
|
261
|
+
|
|
262
|
+
**File**: `.specweave/sync-metadata.json`
|
|
263
|
+
|
|
264
|
+
```json
|
|
265
|
+
{
|
|
266
|
+
"github": {
|
|
267
|
+
"lastImport": "2025-11-19T10:30:00Z",
|
|
268
|
+
"lastImportCount": 150,
|
|
269
|
+
"lastSkippedCount": 5,
|
|
270
|
+
"lastSyncResult": "success"
|
|
271
|
+
},
|
|
272
|
+
"jira": {
|
|
273
|
+
"lastImport": "2025-11-19T10:32:00Z",
|
|
274
|
+
"lastImportCount": 12,
|
|
275
|
+
"lastSkippedCount": 3,
|
|
276
|
+
"lastSyncResult": "success"
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
- `lastImport`: Timestamp of most recent successful import
|
|
282
|
+
- `lastImportCount`: Number of items imported in last sync
|
|
283
|
+
- `lastSkippedCount`: Number of duplicates skipped
|
|
284
|
+
- `lastSyncResult`: `success`, `partial`, or `failed`
|
|
285
|
+
|
|
286
|
+
## Living Docs Structure
|
|
287
|
+
|
|
288
|
+
Imported items create living docs files with E suffix:
|
|
289
|
+
|
|
290
|
+
```
|
|
291
|
+
.specweave/docs/internal/specs/
|
|
292
|
+
āāā FS-042E/ ā Feature (external)
|
|
293
|
+
ā āāā README.md ā Feature metadata
|
|
294
|
+
ā āāā us-001e-login.md ā User Story (external)
|
|
295
|
+
ā āāā us-002e-signup.md ā User Story (external)
|
|
296
|
+
āāā FS-043E/ ā Feature (external)
|
|
297
|
+
āāā us-001e-api-auth.md ā User Story (external)
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### User Story File Format
|
|
301
|
+
|
|
302
|
+
```markdown
|
|
303
|
+
---
|
|
304
|
+
us_id: US-001E
|
|
305
|
+
title: "User Login"
|
|
306
|
+
feature_id: FS-042E
|
|
307
|
+
origin: external
|
|
308
|
+
external_platform: github
|
|
309
|
+
external_id: GH-#638
|
|
310
|
+
external_url: https://github.com/owner/repo/issues/638
|
|
311
|
+
imported_at: 2025-11-19T10:30:00Z
|
|
312
|
+
status: open
|
|
313
|
+
---
|
|
314
|
+
|
|
315
|
+
# US-001E: User Login
|
|
316
|
+
|
|
317
|
+
**Origin**: š GitHub (GH-#638)
|
|
318
|
+
|
|
319
|
+
## Description
|
|
320
|
+
|
|
321
|
+
[Original GitHub issue description]
|
|
322
|
+
|
|
323
|
+
## Acceptance Criteria
|
|
324
|
+
|
|
325
|
+
[Parsed from GitHub issue body or comments]
|
|
326
|
+
|
|
327
|
+
## Tasks
|
|
328
|
+
|
|
329
|
+
No tasks defined.
|
|
330
|
+
|
|
331
|
+
## Implementation Notes
|
|
332
|
+
|
|
333
|
+
[Original labels, comments, metadata from GitHub]
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
## When to Use
|
|
337
|
+
|
|
338
|
+
- **After initial setup**: Import new external items created after `specweave init`
|
|
339
|
+
- **Periodic sync**: Weekly/monthly imports to stay in sync with external tools
|
|
340
|
+
- **Brownfield onboarding**: Import historical items missed during initialization
|
|
341
|
+
- **Cross-team collaboration**: Pull work items from other teams' external tools
|
|
342
|
+
|
|
343
|
+
## Limitations
|
|
344
|
+
|
|
345
|
+
- **NO automatic increment creation**: Imported items live in living docs ONLY
|
|
346
|
+
- User must manually create increment when ready to work on external item
|
|
347
|
+
- **Read-only snapshot**: External items are imported as static snapshots
|
|
348
|
+
- No bidirectional sync (external tool ā SpecWeave only)
|
|
349
|
+
- **Pagination**: Large imports (500+ items) may take several minutes
|
|
350
|
+
- **API quota**: Uses GitHub/JIRA/ADO API quota
|
|
351
|
+
- GitHub: 5000 requests/hour (authenticated)
|
|
352
|
+
- JIRA: ~1000 requests/hour (Cloud estimate)
|
|
353
|
+
- ADO: 200 requests/minute
|
|
354
|
+
|
|
355
|
+
## Differences from `specweave init`
|
|
356
|
+
|
|
357
|
+
| Feature | `specweave init` | `/specweave:import-external` |
|
|
358
|
+
|---------|------------------|------------------------------|
|
|
359
|
+
| When to use | First-time setup | Ongoing imports after init |
|
|
360
|
+
| User prompts | Interactive setup | Minimal prompts (confirmation only) |
|
|
361
|
+
| Time range | Configurable (default: 1 month) | Since last import (default) |
|
|
362
|
+
| Config update | Creates `.specweave/config.json` | Uses existing config |
|
|
363
|
+
| Primary use case | Brownfield onboarding | Stay in sync with external tools |
|
|
364
|
+
|
|
365
|
+
## Troubleshooting
|
|
366
|
+
|
|
367
|
+
### Error: "No platforms configured"
|
|
368
|
+
|
|
369
|
+
```
|
|
370
|
+
ā No external platforms configured.
|
|
371
|
+
|
|
372
|
+
š” Ensure one of these is set:
|
|
373
|
+
- GitHub: GITHUB_TOKEN + .git/config remote
|
|
374
|
+
- JIRA: JIRA_HOST + JIRA_EMAIL + JIRA_API_TOKEN
|
|
375
|
+
- Azure DevOps: ADO_ORG_URL + ADO_PROJECT + ADO_PAT
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
**Solution**: Set environment variables for at least one platform
|
|
379
|
+
|
|
380
|
+
### Error: "Rate limit exceeded"
|
|
381
|
+
|
|
382
|
+
```
|
|
383
|
+
ā GitHub rate limit exceeded (0/5000 remaining).
|
|
384
|
+
Resets at: 10:45 AM (in 300 seconds)
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
**Solution**: Wait for rate limit reset, or use platform filter (`--jira-only`) to avoid GitHub
|
|
388
|
+
|
|
389
|
+
### Warning: "Found 0 items to import"
|
|
390
|
+
|
|
391
|
+
```
|
|
392
|
+
ā ļø No new items found since last import (2025-11-19T10:30:00Z).
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
**Solution**: This is expected if no new work items created since last import. Use `--since=all` to re-import all items (will skip duplicates).
|
|
396
|
+
|
|
397
|
+
## See Also
|
|
398
|
+
|
|
399
|
+
- `specweave init` - Initial project setup with external tool import
|
|
400
|
+
- [External Import Guide](https://docs.spec-weave.com/guides/external-import)
|
|
401
|
+
- [GitHub Integration](https://docs.spec-weave.com/integrations/github)
|
|
402
|
+
- [JIRA Integration](https://docs.spec-weave.com/integrations/jira)
|
|
403
|
+
- [Azure DevOps Integration](https://docs.spec-weave.com/integrations/ado)
|
|
404
|
+
|
|
405
|
+
---
|
|
406
|
+
|
|
407
|
+
**Implementation**: `src/cli/commands/import-external.ts`
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# Post-Edit Hook: Update Status Line After spec.md or tasks.md Edits
|
|
4
|
+
#
|
|
5
|
+
# Triggers: After Edit tool modifies spec.md (AC updates) or tasks.md (task completion)
|
|
6
|
+
# Action: Updates status line cache to reflect latest AC/task progress
|
|
7
|
+
#
|
|
8
|
+
# This ensures status line stays in sync when ACs are marked complete via Edit tool
|
|
9
|
+
# (not just TodoWrite, which only tracks internal todo lists)
|
|
10
|
+
|
|
11
|
+
set -e
|
|
12
|
+
|
|
13
|
+
# Find project root
|
|
14
|
+
find_project_root() {
|
|
15
|
+
local dir="$PWD"
|
|
16
|
+
while [[ "$dir" != "/" ]]; do
|
|
17
|
+
if [[ -d "$dir/.specweave" ]]; then
|
|
18
|
+
echo "$dir"
|
|
19
|
+
return 0
|
|
20
|
+
fi
|
|
21
|
+
dir=$(dirname "$dir")
|
|
22
|
+
done
|
|
23
|
+
echo "$PWD"
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
PROJECT_ROOT=$(find_project_root)
|
|
27
|
+
|
|
28
|
+
# Get the file that was edited from TOOL_USE_CONTENT environment variable
|
|
29
|
+
# Claude Code provides this in the hook context
|
|
30
|
+
EDITED_FILE="${TOOL_USE_CONTENT:-}"
|
|
31
|
+
|
|
32
|
+
# Only update status line if spec.md or tasks.md was edited
|
|
33
|
+
if [[ "$EDITED_FILE" == *"/spec.md"* ]] || [[ "$EDITED_FILE" == *"/tasks.md"* ]]; then
|
|
34
|
+
# Check if the edit is in an increment folder
|
|
35
|
+
if [[ "$EDITED_FILE" == *"/.specweave/increments/"* ]]; then
|
|
36
|
+
# Run status line update
|
|
37
|
+
"$PROJECT_ROOT/plugins/specweave/hooks/lib/update-status-line.sh" &>/dev/null || true
|
|
38
|
+
fi
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
exit 0
|
|
File without changes
|
|
File without changes
|
|
@@ -200,11 +200,20 @@ fi
|
|
|
200
200
|
|
|
201
201
|
if command -v node &> /dev/null; then
|
|
202
202
|
if [ -n "$CURRENT_INCREMENT" ]; then
|
|
203
|
-
echo "[$(date)] š Checking living docs sync for $CURRENT_INCREMENT" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
204
|
-
|
|
205
203
|
# ========================================================================
|
|
206
|
-
#
|
|
204
|
+
# SKIP ARCHIVED INCREMENTS (CRITICAL - prevents folder recreation)
|
|
207
205
|
# ========================================================================
|
|
206
|
+
# If increment is archived, skip living docs sync entirely
|
|
207
|
+
# This prevents recreating archived feature folders in active location
|
|
208
|
+
# See: ULTRATHINK-ARCHIVE-REORGANIZATION-BUG.md for full analysis
|
|
209
|
+
if [ -d ".specweave/increments/_archive/$CURRENT_INCREMENT" ]; then
|
|
210
|
+
echo "[$(date)] āļø Skipping living docs sync for archived increment $CURRENT_INCREMENT" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
211
|
+
else
|
|
212
|
+
echo "[$(date)] š Checking living docs sync for $CURRENT_INCREMENT" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
213
|
+
|
|
214
|
+
# ========================================================================
|
|
215
|
+
# EXTRACT FEATURE ID (NEW in v0.23.0 - Increment 0047: US-Task Linkage)
|
|
216
|
+
# ========================================================================
|
|
208
217
|
# Extract epic field from spec.md frontmatter (e.g., epic: FS-047)
|
|
209
218
|
# This ensures sync uses the explicitly defined feature ID rather than
|
|
210
219
|
# auto-generating one, maintaining traceability with living docs structure.
|
|
@@ -290,6 +299,7 @@ if command -v node &> /dev/null; then
|
|
|
290
299
|
else
|
|
291
300
|
echo "[$(date)] ā ļø sync-living-docs.js not found in any location" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
292
301
|
fi
|
|
302
|
+
fi # Close the archive check 'else' block
|
|
293
303
|
fi
|
|
294
304
|
fi
|
|
295
305
|
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# Post-Write Hook: Update Status Line After spec.md or tasks.md Writes
|
|
4
|
+
#
|
|
5
|
+
# Triggers: After Write tool creates/replaces spec.md or tasks.md
|
|
6
|
+
# Action: Updates status line cache to reflect latest AC/task progress
|
|
7
|
+
|
|
8
|
+
set -e
|
|
9
|
+
|
|
10
|
+
# Find project root
|
|
11
|
+
find_project_root() {
|
|
12
|
+
local dir="$PWD"
|
|
13
|
+
while [[ "$dir" != "/" ]]; do
|
|
14
|
+
if [[ -d "$dir/.specweave" ]]; then
|
|
15
|
+
echo "$dir"
|
|
16
|
+
return 0
|
|
17
|
+
fi
|
|
18
|
+
dir=$(dirname "$dir")
|
|
19
|
+
done
|
|
20
|
+
echo "$PWD"
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
PROJECT_ROOT=$(find_project_root)
|
|
24
|
+
|
|
25
|
+
# Get the file that was written from TOOL_USE_CONTENT environment variable
|
|
26
|
+
WRITTEN_FILE="${TOOL_USE_CONTENT:-}"
|
|
27
|
+
|
|
28
|
+
# Only update status line if spec.md or tasks.md was written
|
|
29
|
+
if [[ "$WRITTEN_FILE" == *"/spec.md"* ]] || [[ "$WRITTEN_FILE" == *"/tasks.md"* ]]; then
|
|
30
|
+
# Check if the write is in an increment folder
|
|
31
|
+
if [[ "$WRITTEN_FILE" == *"/.specweave/increments/"* ]]; then
|
|
32
|
+
# Run status line update
|
|
33
|
+
"$PROJECT_ROOT/plugins/specweave/hooks/lib/update-status-line.sh" &>/dev/null || true
|
|
34
|
+
fi
|
|
35
|
+
fi
|
|
36
|
+
|
|
37
|
+
exit 0
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { AutoTransitionManager } from "
|
|
2
|
+
import { AutoTransitionManager } from "../vendor/core/increment/auto-transition-manager.js";
|
|
3
3
|
async function main() {
|
|
4
4
|
const event = process.argv[2];
|
|
5
5
|
const incrementId = process.argv[3];
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
* node auto-transition.ts auto-correct 0039-ultra-smart-next-command
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
|
-
import { AutoTransitionManager } from '
|
|
22
|
+
import { AutoTransitionManager } from '../vendor/core/increment/auto-transition-manager.js';
|
|
23
23
|
|
|
24
24
|
async function main() {
|
|
25
25
|
const event = process.argv[2];
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
prepareTranslation,
|
|
5
5
|
postProcessTranslation,
|
|
6
6
|
getLanguageName
|
|
7
|
-
} from "
|
|
7
|
+
} from "../vendor/utils/translation.js";
|
|
8
8
|
async function invokeTranslatorSkill(content, sourceLang, targetLang = "en") {
|
|
9
9
|
try {
|
|
10
10
|
const prepared = prepareTranslation(content, sourceLang, targetLang);
|
|
@@ -54,7 +54,9 @@ async function syncLivingDocs(incrementId) {
|
|
|
54
54
|
return;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
// T-034E: Use FormatPreservationSyncService for origin-aware sync
|
|
58
|
+
await syncWithFormatPreservation(incrementId);
|
|
59
|
+
|
|
58
60
|
console.log("\u2705 Living docs sync complete\n");
|
|
59
61
|
} catch (error) {
|
|
60
62
|
console.error("\u274C Error syncing living docs:", error);
|
|
@@ -334,6 +336,38 @@ if (isMainModule) {
|
|
|
334
336
|
console.error("\u274C Fatal error:", error);
|
|
335
337
|
});
|
|
336
338
|
}
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* Sync with format preservation (T-034E)
|
|
342
|
+
* Routes sync based on origin metadata (external vs internal)
|
|
343
|
+
*/
|
|
344
|
+
async function syncWithFormatPreservation(incrementId) {
|
|
345
|
+
try {
|
|
346
|
+
console.log("\nš Using format-preserving sync...");
|
|
347
|
+
|
|
348
|
+
const { SyncCoordinator } = await import("../../../../dist/src/sync/sync-coordinator.js");
|
|
349
|
+
|
|
350
|
+
const coordinator = new SyncCoordinator({
|
|
351
|
+
projectRoot: process.cwd(),
|
|
352
|
+
incrementId
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
const result = await coordinator.syncIncrementCompletion();
|
|
356
|
+
|
|
357
|
+
if (result.success) {
|
|
358
|
+
console.log(`ā
Format-preserving sync complete (${result.syncMode} mode)`);
|
|
359
|
+
console.log(` ${result.userStoriesSynced} user story/stories synced`);
|
|
360
|
+
} else {
|
|
361
|
+
console.log(`ā ļø Sync completed with ${result.errors.length} error(s)`);
|
|
362
|
+
result.errors.forEach(err => console.error(` - ${err}`));
|
|
363
|
+
}
|
|
364
|
+
} catch (error) {
|
|
365
|
+
console.error("ā ļø Format-preserving sync error:", error);
|
|
366
|
+
console.log(" Falling back to legacy sync...");
|
|
367
|
+
// Don't fail - just log and continue
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
337
371
|
export {
|
|
338
372
|
syncLivingDocs
|
|
339
373
|
};
|