specweave 0.22.14 ā 0.23.1
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/cli/helpers/issue-tracker/index.d.ts.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/index.js +5 -17
- package/dist/src/cli/helpers/issue-tracker/index.js.map +1 -1
- 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/repo-structure/repo-id-generator.d.ts +20 -0
- package/dist/src/core/repo-structure/repo-id-generator.d.ts.map +1 -1
- package/dist/src/core/repo-structure/repo-id-generator.js +44 -0
- package/dist/src/core/repo-structure/repo-id-generator.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 +5 -2
- package/dist/src/core/repo-structure/repo-structure-manager.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-archive.md +51 -15
- 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 +94 -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 +91 -0
- package/plugins/specweave/lib/hooks/auto-transition.js +1 -1
- package/plugins/specweave/lib/hooks/auto-transition.js.bak +50 -0
- package/plugins/specweave/lib/hooks/auto-transition.ts +1 -1
- package/plugins/specweave/lib/hooks/auto-transition.ts.bak +84 -0
- package/plugins/specweave/lib/hooks/git-diff-analyzer.d.js.bak +0 -0
- package/plugins/specweave/lib/hooks/git-diff-analyzer.d.ts.bak +89 -0
- package/plugins/specweave/lib/hooks/git-diff-analyzer.js.bak +142 -0
- package/plugins/specweave/lib/hooks/git-diff-analyzer.ts.bak +269 -0
- package/plugins/specweave/lib/hooks/invoke-translator-skill.d.js.bak +0 -0
- package/plugins/specweave/lib/hooks/invoke-translator-skill.d.ts.bak +60 -0
- package/plugins/specweave/lib/hooks/invoke-translator-skill.js +1 -1
- package/plugins/specweave/lib/hooks/invoke-translator-skill.js.bak +155 -0
- package/plugins/specweave/lib/hooks/invoke-translator-skill.ts +1 -1
- package/plugins/specweave/lib/hooks/invoke-translator-skill.ts.bak +264 -0
- package/plugins/specweave/lib/hooks/prepare-reflection-context.d.js.bak +0 -0
- package/plugins/specweave/lib/hooks/prepare-reflection-context.d.ts.bak +42 -0
- package/plugins/specweave/lib/hooks/prepare-reflection-context.js.bak +110 -0
- package/plugins/specweave/lib/hooks/prepare-reflection-context.ts.bak +178 -0
- package/plugins/specweave/lib/hooks/reflection-config-loader.d.js.bak +0 -0
- package/plugins/specweave/lib/hooks/reflection-config-loader.d.ts.bak +45 -0
- package/plugins/specweave/lib/hooks/reflection-config-loader.js.bak +92 -0
- package/plugins/specweave/lib/hooks/reflection-config-loader.ts.bak +156 -0
- package/plugins/specweave/lib/hooks/reflection-parser.d.js.bak +0 -0
- package/plugins/specweave/lib/hooks/reflection-parser.d.ts.bak +33 -0
- package/plugins/specweave/lib/hooks/reflection-parser.js.bak +301 -0
- package/plugins/specweave/lib/hooks/reflection-parser.ts.bak +484 -0
- package/plugins/specweave/lib/hooks/reflection-prompt-builder.d.js.bak +0 -0
- package/plugins/specweave/lib/hooks/reflection-prompt-builder.d.ts.bak +56 -0
- package/plugins/specweave/lib/hooks/reflection-prompt-builder.js.bak +182 -0
- package/plugins/specweave/lib/hooks/reflection-prompt-builder.ts.bak +306 -0
- package/plugins/specweave/lib/hooks/reflection-storage.d.js.bak +0 -0
- package/plugins/specweave/lib/hooks/reflection-storage.d.ts.bak +64 -0
- package/plugins/specweave/lib/hooks/reflection-storage.js.bak +231 -0
- package/plugins/specweave/lib/hooks/reflection-storage.ts.bak +369 -0
- package/plugins/specweave/lib/hooks/run-self-reflection.d.js.bak +0 -0
- package/plugins/specweave/lib/hooks/run-self-reflection.d.ts.bak +43 -0
- package/plugins/specweave/lib/hooks/run-self-reflection.js.bak +132 -0
- package/plugins/specweave/lib/hooks/run-self-reflection.ts.bak +258 -0
- package/plugins/specweave/lib/hooks/sync-cache.js.bak +294 -0
- package/plugins/specweave/lib/hooks/sync-living-docs.d.js.bak +1 -0
- package/plugins/specweave/lib/hooks/sync-living-docs.d.ts.bak +27 -0
- package/plugins/specweave/lib/hooks/sync-living-docs.js +35 -1
- package/plugins/specweave/lib/hooks/sync-living-docs.js.bak +339 -0
- package/plugins/specweave/lib/hooks/sync-us-tasks.js +179 -3
- package/plugins/specweave/lib/hooks/sync-us-tasks.js.bak +476 -0
- package/plugins/specweave/lib/hooks/translate-file.d.js.bak +0 -0
- package/plugins/specweave/lib/hooks/translate-file.d.ts.bak +59 -0
- package/plugins/specweave/lib/hooks/translate-file.js +1 -1
- package/plugins/specweave/lib/hooks/translate-file.js.bak +289 -0
- package/plugins/specweave/lib/hooks/translate-file.ts +1 -1
- package/plugins/specweave/lib/hooks/translate-file.ts.bak +428 -0
- package/plugins/specweave/lib/hooks/translate-living-docs.d.js.bak +0 -0
- package/plugins/specweave/lib/hooks/translate-living-docs.d.ts.bak +13 -0
- package/plugins/specweave/lib/hooks/translate-living-docs.js.bak +119 -0
- package/plugins/specweave/lib/hooks/translate-living-docs.ts.bak +224 -0
- package/plugins/specweave/lib/hooks/update-ac-status.js +1 -1
- package/plugins/specweave/lib/hooks/update-ac-status.js.bak +51 -0
- package/plugins/specweave/lib/hooks/update-ac-status.ts +1 -1
- package/plugins/specweave/lib/hooks/update-ac-status.ts.bak +103 -0
- package/plugins/specweave/lib/hooks/update-tasks-md.d.js.bak +1 -0
- package/plugins/specweave/lib/hooks/update-tasks-md.d.ts.bak +29 -0
- package/plugins/specweave/lib/hooks/update-tasks-md.js.bak +296 -0
- package/plugins/specweave/lib/hooks/update-tasks-md.ts.bak +489 -0
- 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-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-release/hooks/.specweave/logs/dora-tracking.log +531 -0
package/CLAUDE.md
CHANGED
|
@@ -615,6 +615,53 @@ ls .specweave/docs/internal/architecture/adr/*.md | \
|
|
|
615
615
|
# (Extracts unique numbers only, finds max, adds 1)
|
|
616
616
|
```
|
|
617
617
|
|
|
618
|
+
### 13. Archiving Logic Anti-Patterns (CRITICAL!)
|
|
619
|
+
|
|
620
|
+
**NEVER use string search or substring matching for structured data matching**
|
|
621
|
+
|
|
622
|
+
#### Anti-Pattern #1: String Search for Frontmatter Fields
|
|
623
|
+
|
|
624
|
+
```typescript
|
|
625
|
+
// ā WRONG: Matches ANYWHERE in file (false positives!)
|
|
626
|
+
const content = await fs.readFile('spec.md', 'utf-8');
|
|
627
|
+
if (content.includes('FS-039')) {
|
|
628
|
+
// This matches:
|
|
629
|
+
// - feature_id: FS-039 ā (correct)
|
|
630
|
+
// - "See FS-039 for details" ā (FALSE POSITIVE!)
|
|
631
|
+
// - [Related](FS-039) ā (FALSE POSITIVE!)
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
// ā
CORRECT: Parse frontmatter explicitly
|
|
635
|
+
const featureIdMatch = content.match(/^feature_id:\s*["']?([^"'\n]+)["']?$/m);
|
|
636
|
+
if (featureIdMatch && featureIdMatch[1].trim() === 'FS-039') {
|
|
637
|
+
// Only matches actual frontmatter field
|
|
638
|
+
}
|
|
639
|
+
```
|
|
640
|
+
|
|
641
|
+
#### Anti-Pattern #2: Substring Matching for IDs
|
|
642
|
+
|
|
643
|
+
```typescript
|
|
644
|
+
// ā WRONG: Substring matching (false positives!)
|
|
645
|
+
const isArchived = archivedList.some(item => item.includes(searchId));
|
|
646
|
+
// "0039-ultra-smart-v2".includes("0039-ultra-smart") ā TRUE (WRONG!)
|
|
647
|
+
|
|
648
|
+
// ā
CORRECT: Exact equality
|
|
649
|
+
const isArchived = archivedList.some(item => item === searchId);
|
|
650
|
+
```
|
|
651
|
+
|
|
652
|
+
**Why This Matters**:
|
|
653
|
+
- **Incident 2025-11-20**: String search caused 11 features to be incorrectly archived
|
|
654
|
+
- Features that merely REFERENCED another feature appeared to BELONG to it
|
|
655
|
+
- Substring matching confused similar IDs as identical
|
|
656
|
+
|
|
657
|
+
**Prevention**:
|
|
658
|
+
1. Always parse structured data (YAML frontmatter, JSON) explicitly
|
|
659
|
+
2. Use exact equality (`===`) for ID matching, never `.includes()`
|
|
660
|
+
3. Add comprehensive logging to show matching decisions
|
|
661
|
+
4. Test with edge cases: references, links, partial matches
|
|
662
|
+
|
|
663
|
+
**See Also**: `.specweave/increments/0047-us-task-linkage/reports/CRITICAL-ARCHIVING-BUGS-FIX.md`
|
|
664
|
+
|
|
618
665
|
---
|
|
619
666
|
|
|
620
667
|
## Project Structure
|
|
@@ -636,6 +683,123 @@ plugins/ # Claude Code components (skills, agents, commands, hook
|
|
|
636
683
|
|
|
637
684
|
---
|
|
638
685
|
|
|
686
|
+
## Plugin Hook Registration (CRITICAL!)
|
|
687
|
+
|
|
688
|
+
**When**: Adding or modifying hooks that respond to Claude Code tool events
|
|
689
|
+
|
|
690
|
+
**Hook Schema Rules** (v0.22.14+):
|
|
691
|
+
1. ā
**ONLY use valid Claude Code hook events** (e.g., PostToolUse, PreToolUse, SessionStart)
|
|
692
|
+
2. ā **NEVER use custom hook names** (e.g., "TodoWrite") as hook events
|
|
693
|
+
3. ā
**Use matchers** to filter which tool calls trigger the hook
|
|
694
|
+
|
|
695
|
+
### Valid Claude Code Hook Events
|
|
696
|
+
|
|
697
|
+
Claude Code supports **only these 10 hook events**:
|
|
698
|
+
- `PostToolUse` - After a tool completes (use this for TodoWrite, Write, Edit, etc.)
|
|
699
|
+
- `PreToolUse` - Before a tool executes
|
|
700
|
+
- `PermissionRequest` - When permission dialogs appear
|
|
701
|
+
- `Notification` - When notifications are sent
|
|
702
|
+
- `UserPromptSubmit` - When users submit prompts
|
|
703
|
+
- `Stop` - When the main agent finishes
|
|
704
|
+
- `SubagentStop` - When subagents finish
|
|
705
|
+
- `PreCompact` - Before compaction operations
|
|
706
|
+
- `SessionStart` - At session initialization
|
|
707
|
+
- `SessionEnd` - When sessions terminate
|
|
708
|
+
|
|
709
|
+
### Correct Hook Registration Format
|
|
710
|
+
|
|
711
|
+
**File**: `plugins/*/. claude-plugin/plugin.json`
|
|
712
|
+
|
|
713
|
+
```json
|
|
714
|
+
{
|
|
715
|
+
"name": "specweave",
|
|
716
|
+
"version": "0.22.14",
|
|
717
|
+
"hooks": {
|
|
718
|
+
"PostToolUse": [
|
|
719
|
+
{
|
|
720
|
+
"matcher": "TodoWrite",
|
|
721
|
+
"hooks": [
|
|
722
|
+
{
|
|
723
|
+
"type": "command",
|
|
724
|
+
"command": "${CLAUDE_PLUGIN_ROOT}/hooks/post-task-completion.sh",
|
|
725
|
+
"timeout": 10
|
|
726
|
+
}
|
|
727
|
+
]
|
|
728
|
+
}
|
|
729
|
+
]
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
```
|
|
733
|
+
|
|
734
|
+
**Schema Breakdown**:
|
|
735
|
+
| Field | Type | Purpose |
|
|
736
|
+
|-------|------|---------|
|
|
737
|
+
| `PostToolUse` | array | Hook event (one of 10 valid events above) |
|
|
738
|
+
| `matcher` | string | Tool name pattern (e.g., "TodoWrite", "Write\|Edit") |
|
|
739
|
+
| `type` | string | Always "command" for shell scripts |
|
|
740
|
+
| `command` | string | Script path (use `${CLAUDE_PLUGIN_ROOT}` for plugin directory) |
|
|
741
|
+
| `timeout` | number | Seconds before timeout (default: 30) |
|
|
742
|
+
|
|
743
|
+
### Common Mistakes (v0.22.13 Bug)
|
|
744
|
+
|
|
745
|
+
ā **WRONG** (Invalid hook event):
|
|
746
|
+
```json
|
|
747
|
+
{
|
|
748
|
+
"hooks": {
|
|
749
|
+
"TodoWrite": {
|
|
750
|
+
"post": "./hooks/post-task-completion.sh"
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
```
|
|
755
|
+
**Error**: `"TodoWrite"` is not a valid Claude Code hook event
|
|
756
|
+
|
|
757
|
+
ā
**CORRECT** (Use PostToolUse with matcher):
|
|
758
|
+
```json
|
|
759
|
+
{
|
|
760
|
+
"hooks": {
|
|
761
|
+
"PostToolUse": [
|
|
762
|
+
{
|
|
763
|
+
"matcher": "TodoWrite",
|
|
764
|
+
"hooks": [{"type": "command", "command": "..."}]
|
|
765
|
+
}
|
|
766
|
+
]
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
```
|
|
770
|
+
|
|
771
|
+
### Testing Hook Registration
|
|
772
|
+
|
|
773
|
+
```bash
|
|
774
|
+
# 1. Update plugin.json with correct schema
|
|
775
|
+
vim plugins/specweave/.claude-plugin/plugin.json
|
|
776
|
+
|
|
777
|
+
# 2. Commit and push
|
|
778
|
+
git add plugins/specweave/.claude-plugin/plugin.json
|
|
779
|
+
git commit -m "fix: correct hook registration schema"
|
|
780
|
+
git push origin develop
|
|
781
|
+
|
|
782
|
+
# 3. Wait 5-10 seconds for marketplace auto-update
|
|
783
|
+
|
|
784
|
+
# 4. Force refresh marketplace (if needed)
|
|
785
|
+
cd ~/.claude/plugins/marketplaces
|
|
786
|
+
rm -rf specweave
|
|
787
|
+
git clone https://github.com/YOUR_USERNAME/specweave.git
|
|
788
|
+
|
|
789
|
+
# 5. Restart Claude Code
|
|
790
|
+
|
|
791
|
+
# 6. Verify no plugin loading errors
|
|
792
|
+
# Should NOT see: "hooks: Invalid input" error
|
|
793
|
+
```
|
|
794
|
+
|
|
795
|
+
### Documentation References
|
|
796
|
+
|
|
797
|
+
- **Claude Code Plugin Hooks**: https://code.claude.com/docs/en/hooks.md
|
|
798
|
+
- **Hooks Reference**: https://code.claude.com/docs/en/hooks-reference.md
|
|
799
|
+
- **Fix History**: See CHANGELOG.md v0.22.14 for the hook schema bug fix
|
|
800
|
+
|
|
801
|
+
---
|
|
802
|
+
|
|
639
803
|
## Development Workflow
|
|
640
804
|
|
|
641
805
|
### Core Commands
|
|
@@ -695,10 +859,23 @@ claude plugin marketplace update specweave
|
|
|
695
859
|
|
|
696
860
|
```bash
|
|
697
861
|
npm run rebuild # Clean + build (use this during development)
|
|
698
|
-
npm run build # Compile TypeScript
|
|
862
|
+
npm run build # Compile TypeScript + copy hook dependencies
|
|
699
863
|
npm run clean # Remove dist/
|
|
700
864
|
```
|
|
701
865
|
|
|
866
|
+
**Build Architecture**:
|
|
867
|
+
1. `tsc` compiles `src/**/*.ts` ā `dist/src/**/*.js`
|
|
868
|
+
2. `copy:locales` copies translation files
|
|
869
|
+
3. `copy:plugins` compiles plugin TypeScript with esbuild
|
|
870
|
+
4. `copy:hook-deps` **NEW**: Copies hook dependencies to vendor/
|
|
871
|
+
|
|
872
|
+
**Hook Dependencies** (NEW in v0.22.15):
|
|
873
|
+
- Problem: Hooks imported from `../../../../dist/src/...` (failed in marketplace)
|
|
874
|
+
- Solution: Copy compiled files to `plugins/*/lib/vendor/`
|
|
875
|
+
- Hooks now import from `../vendor/...` (self-contained)
|
|
876
|
+
- Script: `scripts/copy-hook-dependencies.js`
|
|
877
|
+
- Auto-detect deps: `scripts/find-hook-dependencies.js`
|
|
878
|
+
|
|
702
879
|
**Critical**: Always import with `.js` extensions:
|
|
703
880
|
```typescript
|
|
704
881
|
// ā
CORRECT
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI Command: /specweave:import-external
|
|
3
|
+
*
|
|
4
|
+
* Import external work items from GitHub, JIRA, or Azure DevOps
|
|
5
|
+
*/
|
|
6
|
+
export interface ImportExternalArgs {
|
|
7
|
+
/** Time range filter */
|
|
8
|
+
since?: 'last' | '1m' | '3m' | '6m' | 'all' | string;
|
|
9
|
+
/** Import from GitHub only */
|
|
10
|
+
githubOnly?: boolean;
|
|
11
|
+
/** Import from JIRA only */
|
|
12
|
+
jiraOnly?: boolean;
|
|
13
|
+
/** Import from Azure DevOps only */
|
|
14
|
+
adoOnly?: boolean;
|
|
15
|
+
/** Dry run mode (preview only) */
|
|
16
|
+
dryRun?: boolean;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Import external work items
|
|
20
|
+
*/
|
|
21
|
+
export declare function importExternal(projectRoot: string, args: ImportExternalArgs): Promise<void>;
|
|
22
|
+
//# sourceMappingURL=import-external.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"import-external.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/import-external.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAmBH,MAAM,WAAW,kBAAkB;IACjC,wBAAwB;IACxB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,KAAK,GAAG,MAAM,CAAC;IAErD,8BAA8B;IAC9B,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB,4BAA4B;IAC5B,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB,oCAAoC;IACpC,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB,kCAAkC;IAClC,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAiHD;;GAEG;AACH,wBAAsB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CA4LjG"}
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI Command: /specweave:import-external
|
|
3
|
+
*
|
|
4
|
+
* Import external work items from GitHub, JIRA, or Azure DevOps
|
|
5
|
+
*/
|
|
6
|
+
import inquirer from 'inquirer';
|
|
7
|
+
import ora from 'ora';
|
|
8
|
+
import chalk from 'chalk';
|
|
9
|
+
import { ImportCoordinator } from '../../importers/import-coordinator.js';
|
|
10
|
+
import { ItemConverter } from '../../importers/item-converter.js';
|
|
11
|
+
import { getLastImportTimestamp } from '../../sync/sync-metadata.js';
|
|
12
|
+
import { RateLimiter } from '../../importers/rate-limiter.js';
|
|
13
|
+
import { shouldConfirmLargeImport } from '../../importers/rate-limiter.js';
|
|
14
|
+
import path from 'path';
|
|
15
|
+
import fs from 'fs-extra';
|
|
16
|
+
/**
|
|
17
|
+
* Detect configured external tools from environment
|
|
18
|
+
*/
|
|
19
|
+
function detectConfiguredTools() {
|
|
20
|
+
const config = {};
|
|
21
|
+
// GitHub detection
|
|
22
|
+
const githubToken = process.env.GITHUB_TOKEN;
|
|
23
|
+
if (githubToken) {
|
|
24
|
+
// Try to parse git remote
|
|
25
|
+
const gitConfigPath = path.join(process.cwd(), '.git', 'config');
|
|
26
|
+
if (fs.existsSync(gitConfigPath)) {
|
|
27
|
+
const gitConfig = fs.readFileSync(gitConfigPath, 'utf-8');
|
|
28
|
+
const remoteMatch = gitConfig.match(/url\s*=\s*(?:https?:\/\/github\.com\/|git@github\.com:)([^/]+)\/([^.\n]+)/);
|
|
29
|
+
if (remoteMatch) {
|
|
30
|
+
config.github = {
|
|
31
|
+
owner: remoteMatch[1],
|
|
32
|
+
repo: remoteMatch[2],
|
|
33
|
+
token: githubToken,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
// JIRA detection
|
|
39
|
+
const jiraHost = process.env.JIRA_HOST;
|
|
40
|
+
const jiraEmail = process.env.JIRA_EMAIL;
|
|
41
|
+
const jiraApiToken = process.env.JIRA_API_TOKEN;
|
|
42
|
+
if (jiraHost) {
|
|
43
|
+
config.jira = {
|
|
44
|
+
host: jiraHost,
|
|
45
|
+
email: jiraEmail,
|
|
46
|
+
apiToken: jiraApiToken,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
// Azure DevOps detection
|
|
50
|
+
const adoOrgUrl = process.env.ADO_ORG_URL;
|
|
51
|
+
const adoProject = process.env.ADO_PROJECT;
|
|
52
|
+
const adoPat = process.env.ADO_PAT;
|
|
53
|
+
if (adoOrgUrl && adoProject) {
|
|
54
|
+
config.ado = {
|
|
55
|
+
orgUrl: adoOrgUrl,
|
|
56
|
+
project: adoProject,
|
|
57
|
+
pat: adoPat,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
return config;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Parse time range filter to import config
|
|
64
|
+
*/
|
|
65
|
+
function parseTimeRange(since, platform, projectRoot) {
|
|
66
|
+
if (since === 'all') {
|
|
67
|
+
return undefined; // No time filter
|
|
68
|
+
}
|
|
69
|
+
if (since === 'last') {
|
|
70
|
+
// Use last import timestamp from sync metadata
|
|
71
|
+
const lastImport = getLastImportTimestamp(projectRoot, platform);
|
|
72
|
+
if (!lastImport) {
|
|
73
|
+
// No previous import, default to 1 month
|
|
74
|
+
return 1;
|
|
75
|
+
}
|
|
76
|
+
// Calculate months since last import
|
|
77
|
+
const lastImportDate = new Date(lastImport);
|
|
78
|
+
const now = new Date();
|
|
79
|
+
const monthsSince = (now.getTime() - lastImportDate.getTime()) / (1000 * 60 * 60 * 24 * 30);
|
|
80
|
+
return Math.ceil(monthsSince);
|
|
81
|
+
}
|
|
82
|
+
// Parse relative time ranges (1m, 3m, 6m)
|
|
83
|
+
const monthMatch = since.match(/^(\d+)m$/);
|
|
84
|
+
if (monthMatch) {
|
|
85
|
+
return parseInt(monthMatch[1], 10);
|
|
86
|
+
}
|
|
87
|
+
// Parse absolute date (ISO format: YYYY-MM-DD)
|
|
88
|
+
const dateMatch = since.match(/^\d{4}-\d{2}-\d{2}$/);
|
|
89
|
+
if (dateMatch) {
|
|
90
|
+
const targetDate = new Date(since);
|
|
91
|
+
const now = new Date();
|
|
92
|
+
const monthsSince = (now.getTime() - targetDate.getTime()) / (1000 * 60 * 60 * 24 * 30);
|
|
93
|
+
return Math.ceil(monthsSince);
|
|
94
|
+
}
|
|
95
|
+
// Default: 1 month
|
|
96
|
+
return 1;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Get platform emoji
|
|
100
|
+
*/
|
|
101
|
+
function getPlatformEmoji(platform) {
|
|
102
|
+
switch (platform) {
|
|
103
|
+
case 'github':
|
|
104
|
+
return 'š';
|
|
105
|
+
case 'jira':
|
|
106
|
+
return 'š«';
|
|
107
|
+
case 'ado':
|
|
108
|
+
return 'š';
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Import external work items
|
|
113
|
+
*/
|
|
114
|
+
export async function importExternal(projectRoot, args) {
|
|
115
|
+
console.log(chalk.bold('\nš„ Import External Work Items\n'));
|
|
116
|
+
try {
|
|
117
|
+
// Detect configured tools
|
|
118
|
+
const configuredTools = detectConfiguredTools();
|
|
119
|
+
// Apply platform filters
|
|
120
|
+
const config = {};
|
|
121
|
+
if (args.githubOnly) {
|
|
122
|
+
if (configuredTools.github) {
|
|
123
|
+
config.github = configuredTools.github;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
else if (args.jiraOnly) {
|
|
127
|
+
if (configuredTools.jira) {
|
|
128
|
+
config.jira = configuredTools.jira;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
else if (args.adoOnly) {
|
|
132
|
+
if (configuredTools.ado) {
|
|
133
|
+
config.ado = configuredTools.ado;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
// All platforms
|
|
138
|
+
Object.assign(config, configuredTools);
|
|
139
|
+
}
|
|
140
|
+
// Validate at least one platform configured
|
|
141
|
+
if (!config.github && !config.jira && !config.ado) {
|
|
142
|
+
throw new Error('No external platforms configured.\n\n' +
|
|
143
|
+
'š” Ensure one of these is set:\n' +
|
|
144
|
+
' - GitHub: GITHUB_TOKEN + .git/config remote\n' +
|
|
145
|
+
' - JIRA: JIRA_HOST + JIRA_EMAIL + JIRA_API_TOKEN\n' +
|
|
146
|
+
' - Azure DevOps: ADO_ORG_URL + ADO_PROJECT + ADO_PAT');
|
|
147
|
+
}
|
|
148
|
+
// Determine time range (default: since last import)
|
|
149
|
+
const since = args.since || 'last';
|
|
150
|
+
// Configure import coordinator
|
|
151
|
+
const importConfig = {
|
|
152
|
+
timeRangeMonths: parseTimeRange(since, 'github', projectRoot),
|
|
153
|
+
};
|
|
154
|
+
const coordinatorConfig = {
|
|
155
|
+
...config,
|
|
156
|
+
importConfig,
|
|
157
|
+
projectRoot,
|
|
158
|
+
enableSyncMetadata: !args.dryRun, // Only update sync metadata if not dry run
|
|
159
|
+
enableRateLimiting: true,
|
|
160
|
+
onProgress: (platform, count, total) => {
|
|
161
|
+
// Progress callback handled by spinner
|
|
162
|
+
},
|
|
163
|
+
onRateLimitWarning: (platform, rateLimitInfo) => {
|
|
164
|
+
const rateLimiter = new RateLimiter();
|
|
165
|
+
console.log(chalk.yellow(`\n${rateLimiter.formatWarning(rateLimitInfo)}\n`));
|
|
166
|
+
},
|
|
167
|
+
onRateLimitPause: (platform, seconds) => {
|
|
168
|
+
const rateLimiter = new RateLimiter();
|
|
169
|
+
console.log(chalk.yellow(`\n${rateLimiter.formatPauseMessage(platform, seconds)}\n`));
|
|
170
|
+
},
|
|
171
|
+
};
|
|
172
|
+
// Create import coordinator
|
|
173
|
+
const coordinator = new ImportCoordinator(coordinatorConfig);
|
|
174
|
+
const platforms = coordinator.getConfiguredPlatforms();
|
|
175
|
+
// Show configuration summary
|
|
176
|
+
if (!args.dryRun) {
|
|
177
|
+
console.log(chalk.dim('š Import Configuration:\n'));
|
|
178
|
+
console.log(chalk.dim(` Platforms: ${platforms.map(p => p.toUpperCase()).join(', ')}`));
|
|
179
|
+
console.log(chalk.dim(` Time range: ${since}`));
|
|
180
|
+
console.log(chalk.dim(` Dry run: ${args.dryRun ? 'Yes' : 'No'}\n`));
|
|
181
|
+
}
|
|
182
|
+
// Import from all platforms
|
|
183
|
+
const allItems = [];
|
|
184
|
+
const platformCounts = {};
|
|
185
|
+
const platformSpinners = {};
|
|
186
|
+
for (const platform of platforms) {
|
|
187
|
+
const spinner = ora({
|
|
188
|
+
text: `Importing from ${platform.toUpperCase()}...`,
|
|
189
|
+
color: 'cyan',
|
|
190
|
+
}).start();
|
|
191
|
+
platformSpinners[platform] = spinner;
|
|
192
|
+
try {
|
|
193
|
+
const result = await coordinator.importFrom(platform);
|
|
194
|
+
allItems.push(...result.items);
|
|
195
|
+
platformCounts[platform] = result.items.length;
|
|
196
|
+
spinner.succeed(`${getPlatformEmoji(platform)} Imported from ${platform.toUpperCase()}: ${result.items.length} items`);
|
|
197
|
+
if (result.errors.length > 0) {
|
|
198
|
+
console.log(chalk.yellow(` ā ļø Warnings: ${result.errors.join(', ')}`));
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
catch (error) {
|
|
202
|
+
spinner.fail(`Failed to import from ${platform.toUpperCase()}: ${error.message}`);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
// Check for large imports (> 100 items)
|
|
206
|
+
if (!args.dryRun && shouldConfirmLargeImport(allItems.length)) {
|
|
207
|
+
console.log(chalk.yellow(`\nā ļø Found ${allItems.length} items to import:`));
|
|
208
|
+
for (const platform of platforms) {
|
|
209
|
+
console.log(chalk.yellow(` - ${platform.toUpperCase()}: ${platformCounts[platform]} items`));
|
|
210
|
+
}
|
|
211
|
+
console.log(chalk.yellow('\n This may take 5-10 minutes and use significant API quota.\n'));
|
|
212
|
+
const { confirm } = await inquirer.prompt([
|
|
213
|
+
{
|
|
214
|
+
type: 'confirm',
|
|
215
|
+
name: 'confirm',
|
|
216
|
+
message: 'Continue?',
|
|
217
|
+
default: true,
|
|
218
|
+
},
|
|
219
|
+
]);
|
|
220
|
+
if (!confirm) {
|
|
221
|
+
console.log(chalk.red('\nā Import cancelled\n'));
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
// Convert items to living docs (or preview in dry-run mode)
|
|
226
|
+
const specsDir = path.join(projectRoot, '.specweave', 'docs', 'internal', 'specs');
|
|
227
|
+
let convertedCount = 0;
|
|
228
|
+
let skippedCount = 0;
|
|
229
|
+
if (args.dryRun) {
|
|
230
|
+
console.log(chalk.cyan('\nš Dry run - no files will be created\n'));
|
|
231
|
+
}
|
|
232
|
+
else {
|
|
233
|
+
const converter = new ItemConverter({
|
|
234
|
+
specsDir,
|
|
235
|
+
projectRoot,
|
|
236
|
+
enableFeatureAllocation: true,
|
|
237
|
+
enableDuplicateDetection: true,
|
|
238
|
+
onDuplicateSkipped: (externalId, existingUsId) => {
|
|
239
|
+
console.log(chalk.dim(` āļø Skipped duplicate: ${externalId} (already imported as ${existingUsId})`));
|
|
240
|
+
},
|
|
241
|
+
});
|
|
242
|
+
const conversionSpinner = ora('Converting items to living docs...').start();
|
|
243
|
+
try {
|
|
244
|
+
const converted = await converter.convertItems(allItems);
|
|
245
|
+
convertedCount = converted.length;
|
|
246
|
+
skippedCount = allItems.length - convertedCount;
|
|
247
|
+
conversionSpinner.succeed(`Converted ${convertedCount} items to living docs`);
|
|
248
|
+
}
|
|
249
|
+
catch (error) {
|
|
250
|
+
conversionSpinner.fail(`Conversion failed: ${error.message}`);
|
|
251
|
+
throw error;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
// Display summary report
|
|
255
|
+
console.log(chalk.bold('\nš Import Summary:\n'));
|
|
256
|
+
if (args.dryRun) {
|
|
257
|
+
console.log(chalk.cyan(' Preview:'));
|
|
258
|
+
for (const platform of platforms) {
|
|
259
|
+
console.log(` ${getPlatformEmoji(platform)} ${platform.toUpperCase()}: ${platformCounts[platform]} items`);
|
|
260
|
+
}
|
|
261
|
+
console.log(` Total: ${allItems.length} items`);
|
|
262
|
+
console.log(chalk.dim('\n ā ļø Remove --dry-run to perform actual import\n'));
|
|
263
|
+
}
|
|
264
|
+
else {
|
|
265
|
+
console.log(` Total imported: ${chalk.green(convertedCount)} items`);
|
|
266
|
+
for (const platform of platforms) {
|
|
267
|
+
console.log(` ${getPlatformEmoji(platform)} ${platform.toUpperCase()}: ${platformCounts[platform]} items`);
|
|
268
|
+
}
|
|
269
|
+
if (skippedCount > 0) {
|
|
270
|
+
console.log(chalk.dim(`\n Duplicates skipped: ${skippedCount} items`));
|
|
271
|
+
}
|
|
272
|
+
console.log(chalk.green('\nā
Import complete!'));
|
|
273
|
+
console.log(chalk.dim(` Living docs updated: ${specsDir}`));
|
|
274
|
+
console.log(chalk.dim(` Sync metadata updated: ${path.join(projectRoot, '.specweave', 'sync-metadata.json')}\n`));
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
catch (error) {
|
|
278
|
+
console.error(chalk.red(`\nā Import failed: ${error.message}\n`));
|
|
279
|
+
throw error;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
//# sourceMappingURL=import-external.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"import-external.js","sourceRoot":"","sources":["../../../../src/cli/commands/import-external.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAkBA,OAAO,EAAE,MAAM,EAAiB,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAkBA,OAAO,EAAE,MAAM,EAAiB,MAAM,uBAAuB,CAAC;AAgB9D,UAAU,WAAW;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AA8ID,wBAAsB,WAAW,CAC/B,WAAW,CAAC,EAAE,MAAM,EACpB,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,IAAI,CAAC,CAwyCf"}
|
|
@@ -19,6 +19,8 @@ import { ItemConverter } from '../../importers/item-converter.js';
|
|
|
19
19
|
import { loadImportConfig } from '../../config/import-config.js';
|
|
20
20
|
const __dirname = getDirname(import.meta.url);
|
|
21
21
|
import { readEnvFile, parseEnvFile } from '../../utils/env-file.js';
|
|
22
|
+
import { selectRepositories } from '../helpers/github-repo-selector.js';
|
|
23
|
+
import { Octokit } from '@octokit/rest';
|
|
22
24
|
/**
|
|
23
25
|
* Detect if we're in the SpecWeave framework repository itself
|
|
24
26
|
* (development mode vs. user project mode)
|
|
@@ -1518,6 +1520,50 @@ async function promptAndRunExternalImport(targetDir, isCI) {
|
|
|
1518
1520
|
platforms: []
|
|
1519
1521
|
};
|
|
1520
1522
|
}
|
|
1523
|
+
// US-011: Multi-Repo Selection for GitHub (if GitHub detected and token available)
|
|
1524
|
+
let repoSelectionConfig = null;
|
|
1525
|
+
if (githubRemote && process.env.GITHUB_TOKEN) {
|
|
1526
|
+
const { useMultiRepo } = await inquirer.prompt([
|
|
1527
|
+
{
|
|
1528
|
+
type: 'confirm',
|
|
1529
|
+
name: 'useMultiRepo',
|
|
1530
|
+
message: 'Do you want to import from multiple repositories?',
|
|
1531
|
+
default: false
|
|
1532
|
+
}
|
|
1533
|
+
]);
|
|
1534
|
+
if (useMultiRepo) {
|
|
1535
|
+
try {
|
|
1536
|
+
const octokit = new Octokit({ auth: process.env.GITHUB_TOKEN });
|
|
1537
|
+
repoSelectionConfig = await selectRepositories(octokit, process.env.GITHUB_TOKEN);
|
|
1538
|
+
if (repoSelectionConfig) {
|
|
1539
|
+
// Save to config.json for future imports
|
|
1540
|
+
const configPath = path.join(targetDir, '.specweave', 'config.json');
|
|
1541
|
+
let config = {};
|
|
1542
|
+
if (fs.existsSync(configPath)) {
|
|
1543
|
+
config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
1544
|
+
}
|
|
1545
|
+
if (!config.github) {
|
|
1546
|
+
config.github = {};
|
|
1547
|
+
}
|
|
1548
|
+
config.github.repositories = repoSelectionConfig.repositories;
|
|
1549
|
+
config.github.selectionStrategy = repoSelectionConfig.selectionStrategy;
|
|
1550
|
+
if (repoSelectionConfig.pattern) {
|
|
1551
|
+
config.github.pattern = repoSelectionConfig.pattern;
|
|
1552
|
+
}
|
|
1553
|
+
if (repoSelectionConfig.organizationName) {
|
|
1554
|
+
config.github.organizationName = repoSelectionConfig.organizationName;
|
|
1555
|
+
}
|
|
1556
|
+
fs.ensureDirSync(path.dirname(configPath));
|
|
1557
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
1558
|
+
console.log(chalk.green(`ā
Repository selection saved to config.json\n`));
|
|
1559
|
+
}
|
|
1560
|
+
}
|
|
1561
|
+
catch (error) {
|
|
1562
|
+
console.error(chalk.yellow(`ā ļø Failed to select repositories: ${error instanceof Error ? error.message : String(error)}`));
|
|
1563
|
+
console.log(chalk.gray('Continuing with single repository import...\n'));
|
|
1564
|
+
}
|
|
1565
|
+
}
|
|
1566
|
+
}
|
|
1521
1567
|
// Map config timeRangeMonths to closest prompt option
|
|
1522
1568
|
let defaultTimeRange = 3; // Default to 3 months
|
|
1523
1569
|
if (importConfig.timeRangeMonths === 1)
|