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.
Files changed (150) hide show
  1. package/CLAUDE.md +178 -1
  2. package/dist/src/cli/commands/import-external.d.ts +22 -0
  3. package/dist/src/cli/commands/import-external.d.ts.map +1 -0
  4. package/dist/src/cli/commands/import-external.js +282 -0
  5. package/dist/src/cli/commands/import-external.js.map +1 -0
  6. package/dist/src/cli/commands/init.d.ts.map +1 -1
  7. package/dist/src/cli/commands/init.js +46 -0
  8. package/dist/src/cli/commands/init.js.map +1 -1
  9. package/dist/src/cli/helpers/github-repo-selector.d.ts +59 -0
  10. package/dist/src/cli/helpers/github-repo-selector.d.ts.map +1 -0
  11. package/dist/src/cli/helpers/github-repo-selector.js +265 -0
  12. package/dist/src/cli/helpers/github-repo-selector.js.map +1 -0
  13. package/dist/src/config/types.d.ts +16 -16
  14. package/dist/src/core/increment/ac-status-manager.d.ts.map +1 -1
  15. package/dist/src/core/increment/ac-status-manager.js +4 -2
  16. package/dist/src/core/increment/ac-status-manager.js.map +1 -1
  17. package/dist/src/core/increment/completion-validator.d.ts +30 -1
  18. package/dist/src/core/increment/completion-validator.d.ts.map +1 -1
  19. package/dist/src/core/increment/completion-validator.js +151 -3
  20. package/dist/src/core/increment/completion-validator.js.map +1 -1
  21. package/dist/src/core/increment/increment-archiver.d.ts +25 -0
  22. package/dist/src/core/increment/increment-archiver.d.ts.map +1 -1
  23. package/dist/src/core/increment/increment-archiver.js +130 -3
  24. package/dist/src/core/increment/increment-archiver.js.map +1 -1
  25. package/dist/src/core/living-docs/feature-archiver.d.ts +37 -0
  26. package/dist/src/core/living-docs/feature-archiver.d.ts.map +1 -1
  27. package/dist/src/core/living-docs/feature-archiver.js +262 -18
  28. package/dist/src/core/living-docs/feature-archiver.js.map +1 -1
  29. package/dist/src/core/living-docs/feature-id-manager.d.ts +17 -0
  30. package/dist/src/core/living-docs/feature-id-manager.d.ts.map +1 -1
  31. package/dist/src/core/living-docs/feature-id-manager.js +25 -0
  32. package/dist/src/core/living-docs/feature-id-manager.js.map +1 -1
  33. package/dist/src/core/living-docs/living-docs-sync.d.ts +14 -0
  34. package/dist/src/core/living-docs/living-docs-sync.d.ts.map +1 -1
  35. package/dist/src/core/living-docs/living-docs-sync.js +46 -0
  36. package/dist/src/core/living-docs/living-docs-sync.js.map +1 -1
  37. package/dist/src/core/sync/sync-event-logger.d.ts +15 -1
  38. package/dist/src/core/sync/sync-event-logger.d.ts.map +1 -1
  39. package/dist/src/core/sync/sync-event-logger.js +39 -1
  40. package/dist/src/core/sync/sync-event-logger.js.map +1 -1
  41. package/dist/src/core/types/sync-config-validator.d.ts +57 -0
  42. package/dist/src/core/types/sync-config-validator.d.ts.map +1 -0
  43. package/dist/src/core/types/sync-config-validator.js +116 -0
  44. package/dist/src/core/types/sync-config-validator.js.map +1 -0
  45. package/dist/src/importers/duplicate-detector.d.ts +107 -0
  46. package/dist/src/importers/duplicate-detector.d.ts.map +1 -0
  47. package/dist/src/importers/duplicate-detector.js +189 -0
  48. package/dist/src/importers/duplicate-detector.js.map +1 -0
  49. package/dist/src/importers/import-coordinator.d.ts +15 -0
  50. package/dist/src/importers/import-coordinator.d.ts.map +1 -1
  51. package/dist/src/importers/import-coordinator.js +43 -1
  52. package/dist/src/importers/import-coordinator.js.map +1 -1
  53. package/dist/src/importers/item-converter.d.ts +5 -0
  54. package/dist/src/importers/item-converter.d.ts.map +1 -1
  55. package/dist/src/importers/item-converter.js +27 -2
  56. package/dist/src/importers/item-converter.js.map +1 -1
  57. package/dist/src/importers/rate-limiter.d.ts +128 -0
  58. package/dist/src/importers/rate-limiter.d.ts.map +1 -0
  59. package/dist/src/importers/rate-limiter.js +200 -0
  60. package/dist/src/importers/rate-limiter.js.map +1 -0
  61. package/dist/src/init/compliance/types.d.ts +2 -2
  62. package/dist/src/integrations/ado/ado-client.d.ts +6 -0
  63. package/dist/src/integrations/ado/ado-client.d.ts.map +1 -1
  64. package/dist/src/integrations/ado/ado-client.js +23 -0
  65. package/dist/src/integrations/ado/ado-client.js.map +1 -1
  66. package/dist/src/integrations/jira/jira-client.d.ts +6 -0
  67. package/dist/src/integrations/jira/jira-client.d.ts.map +1 -1
  68. package/dist/src/integrations/jira/jira-client.js +38 -0
  69. package/dist/src/integrations/jira/jira-client.js.map +1 -1
  70. package/dist/src/sync/external-item-sync-service.d.ts +150 -0
  71. package/dist/src/sync/external-item-sync-service.d.ts.map +1 -0
  72. package/dist/src/sync/external-item-sync-service.js +241 -0
  73. package/dist/src/sync/external-item-sync-service.js.map +1 -0
  74. package/dist/src/sync/format-preservation-sync.d.ts +90 -0
  75. package/dist/src/sync/format-preservation-sync.d.ts.map +1 -0
  76. package/dist/src/sync/format-preservation-sync.js +173 -0
  77. package/dist/src/sync/format-preservation-sync.js.map +1 -0
  78. package/dist/src/sync/index.d.ts +8 -0
  79. package/dist/src/sync/index.d.ts.map +1 -0
  80. package/dist/src/sync/index.js +6 -0
  81. package/dist/src/sync/index.js.map +1 -0
  82. package/dist/src/sync/sync-coordinator.d.ts +49 -0
  83. package/dist/src/sync/sync-coordinator.d.ts.map +1 -0
  84. package/dist/src/sync/sync-coordinator.js +248 -0
  85. package/dist/src/sync/sync-coordinator.js.map +1 -0
  86. package/dist/src/sync/sync-metadata.d.ts +75 -0
  87. package/dist/src/sync/sync-metadata.d.ts.map +1 -0
  88. package/dist/src/sync/sync-metadata.js +100 -0
  89. package/dist/src/sync/sync-metadata.js.map +1 -0
  90. package/dist/src/types/living-docs-us-file.d.ts +63 -0
  91. package/dist/src/types/living-docs-us-file.d.ts.map +1 -0
  92. package/dist/src/types/living-docs-us-file.js +27 -0
  93. package/dist/src/types/living-docs-us-file.js.map +1 -0
  94. package/dist/src/validators/format-preservation-validator.d.ts +127 -0
  95. package/dist/src/validators/format-preservation-validator.d.ts.map +1 -0
  96. package/dist/src/validators/format-preservation-validator.js +187 -0
  97. package/dist/src/validators/format-preservation-validator.js.map +1 -0
  98. package/package.json +3 -2
  99. package/plugins/specweave/.claude-plugin/plugin.json +20 -0
  100. package/plugins/specweave/commands/specweave-archive-features.md +11 -1
  101. package/plugins/specweave/commands/specweave-import-docs.md +88 -278
  102. package/plugins/specweave/commands/specweave-import-external.md +407 -0
  103. package/plugins/specweave/hooks/post-edit-spec.sh +41 -0
  104. package/plugins/specweave/hooks/post-increment-completion.sh +0 -0
  105. package/plugins/specweave/hooks/post-spec-update.sh +0 -0
  106. package/plugins/specweave/hooks/post-task-completion.sh +13 -3
  107. package/plugins/specweave/hooks/post-write-spec.sh +37 -0
  108. package/plugins/specweave/lib/hooks/auto-transition.js +1 -1
  109. package/plugins/specweave/lib/hooks/auto-transition.ts +1 -1
  110. package/plugins/specweave/lib/hooks/invoke-translator-skill.js +1 -1
  111. package/plugins/specweave/lib/hooks/invoke-translator-skill.ts +1 -1
  112. package/plugins/specweave/lib/hooks/sync-living-docs.js +35 -1
  113. package/plugins/specweave/lib/hooks/sync-us-tasks.js +179 -3
  114. package/plugins/specweave/lib/hooks/translate-file.js +1 -1
  115. package/plugins/specweave/lib/hooks/translate-file.ts +1 -1
  116. package/plugins/specweave/lib/hooks/update-ac-status.js +1 -1
  117. package/plugins/specweave/lib/hooks/update-ac-status.ts +1 -1
  118. package/plugins/specweave/lib/vendor/core/increment/ac-status-manager.d.ts +115 -0
  119. package/plugins/specweave/lib/vendor/core/increment/ac-status-manager.js +345 -0
  120. package/plugins/specweave/lib/vendor/core/increment/ac-status-manager.js.map +1 -0
  121. package/plugins/specweave/lib/vendor/core/increment/active-increment-manager.d.ts +106 -0
  122. package/plugins/specweave/lib/vendor/core/increment/active-increment-manager.js +220 -0
  123. package/plugins/specweave/lib/vendor/core/increment/active-increment-manager.js.map +1 -0
  124. package/plugins/specweave/lib/vendor/core/increment/auto-transition-manager.d.ts +60 -0
  125. package/plugins/specweave/lib/vendor/core/increment/auto-transition-manager.js +192 -0
  126. package/plugins/specweave/lib/vendor/core/increment/auto-transition-manager.js.map +1 -0
  127. package/plugins/specweave/lib/vendor/core/increment/duplicate-detector.d.ts +52 -0
  128. package/plugins/specweave/lib/vendor/core/increment/duplicate-detector.js +276 -0
  129. package/plugins/specweave/lib/vendor/core/increment/duplicate-detector.js.map +1 -0
  130. package/plugins/specweave/lib/vendor/core/increment/metadata-manager.d.ts +163 -0
  131. package/plugins/specweave/lib/vendor/core/increment/metadata-manager.js +541 -0
  132. package/plugins/specweave/lib/vendor/core/increment/metadata-manager.js.map +1 -0
  133. package/plugins/specweave/lib/vendor/core/types/increment-metadata.d.ts +157 -0
  134. package/plugins/specweave/lib/vendor/core/types/increment-metadata.js +191 -0
  135. package/plugins/specweave/lib/vendor/core/types/increment-metadata.js.map +1 -0
  136. package/plugins/specweave/lib/vendor/generators/spec/task-parser.d.ts +95 -0
  137. package/plugins/specweave/lib/vendor/generators/spec/task-parser.js +301 -0
  138. package/plugins/specweave/lib/vendor/generators/spec/task-parser.js.map +1 -0
  139. package/plugins/specweave/lib/vendor/utils/logger.d.ts +48 -0
  140. package/plugins/specweave/lib/vendor/utils/logger.js +53 -0
  141. package/plugins/specweave/lib/vendor/utils/logger.js.map +1 -0
  142. package/plugins/specweave/lib/vendor/utils/translation.d.ts +187 -0
  143. package/plugins/specweave/lib/vendor/utils/translation.js +414 -0
  144. package/plugins/specweave/lib/vendor/utils/translation.js.map +1 -0
  145. package/plugins/specweave-ado/lib/ado-multi-project-sync.js +0 -1
  146. package/plugins/specweave-github/commands/specweave-github-update-user-story.md +1 -1
  147. package/plugins/specweave-github/skills/github-issue-standard/SKILL.md +1 -1
  148. package/plugins/specweave-jira/lib/enhanced-jira-sync.js +3 -3
  149. package/plugins/specweave-ado/lib/enhanced-ado-sync.js +0 -170
  150. package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +0 -5694
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;AAc9D,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"}
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)