specweave 2.2.2 → 2.3.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 (132) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/README.md +22 -5
  3. package/bin/check-build.js +43 -0
  4. package/bin/check-node.js +136 -0
  5. package/bin/help.js +68 -0
  6. package/bin/project.js +28 -0
  7. package/bin/specweave.js +26 -305
  8. package/bin/startup-check.js +44 -0
  9. package/dist/dashboard/assets/index-DS3yH-sX.css +1 -0
  10. package/dist/dashboard/assets/index-DjfDqgzX.js +13 -0
  11. package/dist/dashboard/assets/web-0-CXU3YvQl.woff2 +0 -0
  12. package/dist/dashboard/assets/web-1-CnEgTPdE.woff2 +0 -0
  13. package/dist/dashboard/assets/web-10-ppjp2k5c.woff2 +0 -0
  14. package/dist/dashboard/assets/web-11-T5L87s1n.woff2 +0 -0
  15. package/dist/dashboard/assets/web-2-Cuw1d432.woff2 +0 -0
  16. package/dist/dashboard/assets/web-3-tuJ4lY6O.woff2 +0 -0
  17. package/dist/dashboard/assets/web-4-KUPCjGsn.woff2 +0 -0
  18. package/dist/dashboard/assets/web-5-BD64o3ke.woff2 +0 -0
  19. package/dist/dashboard/assets/web-6-CuVUMDWO.woff2 +0 -0
  20. package/dist/dashboard/assets/web-7-B2O-dwcv.woff2 +0 -0
  21. package/dist/dashboard/assets/web-8-b0I-AwbV.woff2 +0 -0
  22. package/dist/dashboard/assets/web-9-CjmLAiqB.woff2 +0 -0
  23. package/dist/dashboard/index.html +3 -3
  24. package/dist/src/adapters/codex/README.md +5 -101
  25. package/dist/src/adapters/codex/adapter.d.ts +5 -6
  26. package/dist/src/adapters/codex/adapter.d.ts.map +1 -1
  27. package/dist/src/adapters/codex/adapter.js +40 -226
  28. package/dist/src/adapters/codex/adapter.js.map +1 -1
  29. package/dist/src/adapters/registry.yaml +1 -1
  30. package/dist/src/cli/commands/dashboard.js +6 -6
  31. package/dist/src/cli/commands/dashboard.js.map +1 -1
  32. package/dist/src/cli/commands/gc.d.ts.map +1 -1
  33. package/dist/src/cli/commands/gc.js +18 -2
  34. package/dist/src/cli/commands/gc.js.map +1 -1
  35. package/dist/src/cli/commands/living-docs.d.ts.map +1 -1
  36. package/dist/src/cli/commands/living-docs.js +12 -6
  37. package/dist/src/cli/commands/living-docs.js.map +1 -1
  38. package/dist/src/cli/commands/lsp.d.ts.map +1 -1
  39. package/dist/src/cli/commands/lsp.js +38 -9
  40. package/dist/src/cli/commands/lsp.js.map +1 -1
  41. package/dist/src/cli/commands/project.d.ts +25 -0
  42. package/dist/src/cli/commands/project.d.ts.map +1 -0
  43. package/dist/src/cli/commands/project.js +123 -0
  44. package/dist/src/cli/commands/project.js.map +1 -0
  45. package/dist/src/cli/commands/refresh-plugins.d.ts +1 -0
  46. package/dist/src/cli/commands/refresh-plugins.d.ts.map +1 -1
  47. package/dist/src/cli/commands/refresh-plugins.js +15 -3
  48. package/dist/src/cli/commands/refresh-plugins.js.map +1 -1
  49. package/dist/src/cli/commands/save.d.ts +10 -2
  50. package/dist/src/cli/commands/save.d.ts.map +1 -1
  51. package/dist/src/cli/commands/save.js +35 -4
  52. package/dist/src/cli/commands/save.js.map +1 -1
  53. package/dist/src/cli/commands/update.d.ts.map +1 -1
  54. package/dist/src/cli/commands/update.js +7 -4
  55. package/dist/src/cli/commands/update.js.map +1 -1
  56. package/dist/src/cli/helpers/init/greenfield-detection.d.ts.map +1 -1
  57. package/dist/src/cli/helpers/init/greenfield-detection.js +12 -13
  58. package/dist/src/cli/helpers/init/greenfield-detection.js.map +1 -1
  59. package/dist/src/config/types.d.ts +4 -4
  60. package/dist/src/core/doctor/checkers/installation-health-checker.d.ts.map +1 -1
  61. package/dist/src/core/doctor/checkers/installation-health-checker.js +10 -0
  62. package/dist/src/core/doctor/checkers/installation-health-checker.js.map +1 -1
  63. package/dist/src/core/jev/browse.d.ts +2 -2
  64. package/dist/src/core/jev/browse.d.ts.map +1 -1
  65. package/dist/src/core/jev/browse.js +57 -11
  66. package/dist/src/core/jev/browse.js.map +1 -1
  67. package/dist/src/core/jev/client.d.ts.map +1 -1
  68. package/dist/src/core/jev/client.js +49 -20
  69. package/dist/src/core/jev/client.js.map +1 -1
  70. package/dist/src/core/jev/decide.d.ts.map +1 -1
  71. package/dist/src/core/jev/decide.js +12 -7
  72. package/dist/src/core/jev/decide.js.map +1 -1
  73. package/dist/src/core/living-docs/discovery.d.ts +6 -0
  74. package/dist/src/core/living-docs/discovery.d.ts.map +1 -1
  75. package/dist/src/core/living-docs/discovery.js +18 -6
  76. package/dist/src/core/living-docs/discovery.js.map +1 -1
  77. package/dist/src/core/lsp/lsp-client.d.ts.map +1 -1
  78. package/dist/src/core/lsp/lsp-client.js +13 -8
  79. package/dist/src/core/lsp/lsp-client.js.map +1 -1
  80. package/dist/src/core/project-hub/brief.d.ts +11 -0
  81. package/dist/src/core/project-hub/brief.d.ts.map +1 -0
  82. package/dist/src/core/project-hub/brief.js +39 -0
  83. package/dist/src/core/project-hub/brief.js.map +1 -0
  84. package/dist/src/core/project-hub/store.d.ts +25 -0
  85. package/dist/src/core/project-hub/store.d.ts.map +1 -0
  86. package/dist/src/core/project-hub/store.js +174 -0
  87. package/dist/src/core/project-hub/store.js.map +1 -0
  88. package/dist/src/core/project-hub/types.d.ts +51 -0
  89. package/dist/src/core/project-hub/types.d.ts.map +1 -0
  90. package/dist/src/core/project-hub/types.js +16 -0
  91. package/dist/src/core/project-hub/types.js.map +1 -0
  92. package/dist/src/core/session/handoff-secret-scrub.d.ts.map +1 -1
  93. package/dist/src/core/session/handoff-secret-scrub.js +2 -1
  94. package/dist/src/core/session/handoff-secret-scrub.js.map +1 -1
  95. package/dist/src/dashboard/server/dashboard-server.d.ts.map +1 -1
  96. package/dist/src/dashboard/server/dashboard-server.js +2 -0
  97. package/dist/src/dashboard/server/dashboard-server.js.map +1 -1
  98. package/dist/src/dashboard/server/data/intent-store.d.ts +5 -0
  99. package/dist/src/dashboard/server/data/intent-store.d.ts.map +1 -1
  100. package/dist/src/dashboard/server/data/intent-store.js +31 -0
  101. package/dist/src/dashboard/server/data/intent-store.js.map +1 -1
  102. package/dist/src/dashboard/server/routes/project-hub-routes.d.ts +5 -0
  103. package/dist/src/dashboard/server/routes/project-hub-routes.d.ts.map +1 -0
  104. package/dist/src/dashboard/server/routes/project-hub-routes.js +75 -0
  105. package/dist/src/dashboard/server/routes/project-hub-routes.js.map +1 -0
  106. package/dist/src/init/compliance/types.d.ts +1 -1
  107. package/dist/src/init/research/types.d.ts +1 -1
  108. package/dist/src/utils/cleanup-stale-plugins.d.ts +9 -0
  109. package/dist/src/utils/cleanup-stale-plugins.d.ts.map +1 -1
  110. package/dist/src/utils/cleanup-stale-plugins.js +40 -23
  111. package/dist/src/utils/cleanup-stale-plugins.js.map +1 -1
  112. package/dist/src/utils/find-project-root.d.ts +23 -0
  113. package/dist/src/utils/find-project-root.d.ts.map +1 -1
  114. package/dist/src/utils/find-project-root.js +26 -4
  115. package/dist/src/utils/find-project-root.js.map +1 -1
  116. package/dist/src/utils/native-skill-installer.d.ts +10 -0
  117. package/dist/src/utils/native-skill-installer.d.ts.map +1 -0
  118. package/dist/src/utils/native-skill-installer.js +79 -0
  119. package/dist/src/utils/native-skill-installer.js.map +1 -0
  120. package/dist/src/utils/plugin-copier.d.ts +9 -0
  121. package/dist/src/utils/plugin-copier.d.ts.map +1 -1
  122. package/dist/src/utils/plugin-copier.js +20 -1
  123. package/dist/src/utils/plugin-copier.js.map +1 -1
  124. package/package.json +4 -3
  125. package/plugins/specweave/.claude-plugin/plugin.json +1 -1
  126. package/plugins/specweave/marketplace.json +6 -0
  127. package/plugins/specweave/skills/project/SKILL.md +45 -0
  128. package/src/styles/fonts/ibmplexsans-OFL.txt +93 -0
  129. package/src/styles/fonts/newsreader-OFL.txt +93 -0
  130. package/src/templates/AGENTS.md.template +4 -0
  131. package/dist/dashboard/assets/index-BeKUULf0.css +0 -1
  132. package/dist/dashboard/assets/index-Bf5TF0_l.js +0 -13
package/bin/specweave.js CHANGED
@@ -7,191 +7,17 @@
7
7
  * Provides commands for initializing projects, creating increments, and managing skills.
8
8
  */
9
9
 
10
- // ============================================================================
11
- // CRITICAL: Node.js Version Check (MUST run before ANY ESM imports)
12
- // ============================================================================
13
- // This check runs synchronously before any imports that use modern syntax
14
- // (like `import ... with { type: 'json' }`) which would crash on older Node.js
15
- // ============================================================================
16
-
17
- const MIN_NODE_VERSION = '20.12.0';
18
- const CURRENT_NODE_VERSION = process.versions.node;
19
-
20
- /**
21
- * Compare semver versions
22
- * @param {string} current - Current version (e.g., "18.17.0")
23
- * @param {string} required - Required version (e.g., "20.12.0")
24
- * @returns {boolean} true if current >= required
25
- */
26
- function isVersionSatisfied(current, required) {
27
- const currentParts = current.split('.').map(Number);
28
- const requiredParts = required.split('.').map(Number);
29
-
30
- for (let i = 0; i < 3; i++) {
31
- const curr = currentParts[i] || 0;
32
- const req = requiredParts[i] || 0;
33
- if (curr > req) return true;
34
- if (curr < req) return false;
35
- }
36
- return true; // Equal versions
37
- }
38
-
39
- /**
40
- * Get platform-specific Node.js upgrade instructions
41
- */
42
- function getUpgradeInstructions() {
43
- const platform = process.platform;
44
- const isNvm = process.env.NVM_DIR || process.env.NVM_BIN;
45
- const isFnm = process.env.FNM_DIR || process.env.FNM_MULTISHELL_PATH;
46
- const isVolta = process.env.VOLTA_HOME;
47
- const isAsdf = process.env.ASDF_DIR;
48
-
49
- let instructions = [];
50
-
51
- // Version manager detection (cross-platform)
52
- if (isNvm) {
53
- instructions.push(' Using nvm (detected):');
54
- instructions.push(' nvm install 22');
55
- instructions.push(' nvm use 22');
56
- instructions.push(' nvm alias default 22');
57
- } else if (isFnm) {
58
- instructions.push(' Using fnm (detected):');
59
- instructions.push(' fnm install 22');
60
- instructions.push(' fnm use 22');
61
- instructions.push(' fnm default 22');
62
- } else if (isVolta) {
63
- instructions.push(' Using Volta (detected):');
64
- instructions.push(' volta install node@22');
65
- } else if (isAsdf) {
66
- instructions.push(' Using asdf (detected):');
67
- instructions.push(' asdf install nodejs 22.0.0');
68
- instructions.push(' asdf global nodejs 22.0.0');
69
- } else {
70
- // Platform-specific fallback
71
- switch (platform) {
72
- case 'darwin':
73
- instructions.push(' macOS options:');
74
- instructions.push(' # Using Homebrew:');
75
- instructions.push(' brew install node@22');
76
- instructions.push('');
77
- instructions.push(' # Using nvm (recommended):');
78
- instructions.push(' curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash');
79
- instructions.push(' nvm install 22 && nvm use 22');
80
- break;
81
- case 'linux':
82
- instructions.push(' Linux options:');
83
- instructions.push(' # Using nvm (recommended):');
84
- instructions.push(' curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash');
85
- instructions.push(' nvm install 22 && nvm use 22');
86
- instructions.push('');
87
- instructions.push(' # Using NodeSource (Debian/Ubuntu):');
88
- instructions.push(' curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -');
89
- instructions.push(' sudo apt-get install -y nodejs');
90
- break;
91
- case 'win32':
92
- instructions.push(' Windows options:');
93
- instructions.push(' # Using nvm-windows:');
94
- instructions.push(' nvm install 22');
95
- instructions.push(' nvm use 22');
96
- instructions.push('');
97
- instructions.push(' # Direct download:');
98
- instructions.push(' https://nodejs.org/en/download/');
99
- break;
100
- default:
101
- instructions.push(' Download Node.js 22+ from:');
102
- instructions.push(' https://nodejs.org/en/download/');
103
- }
104
- }
105
-
106
- return instructions.join('\n');
107
- }
108
-
109
- // Perform the version check
110
- if (!isVersionSatisfied(CURRENT_NODE_VERSION, MIN_NODE_VERSION)) {
111
- // Use basic console methods (no chalk yet - it may fail to import)
112
- const RED = '\x1b[31m';
113
- const YELLOW = '\x1b[33m';
114
- const CYAN = '\x1b[36m';
115
- const BOLD = '\x1b[1m';
116
- const RESET = '\x1b[0m';
117
- const DIM = '\x1b[2m';
118
- const UNDERLINE = '\x1b[4m';
119
-
120
- console.error('');
121
- console.error(`${RED}${BOLD}╔══════════════════════════════════════════════════════════════════╗${RESET}`);
122
- console.error(`${RED}${BOLD}║ SpecWeave requires Node.js ${MIN_NODE_VERSION} or higher ║${RESET}`);
123
- console.error(`${RED}${BOLD}╚══════════════════════════════════════════════════════════════════╝${RESET}`);
124
- console.error('');
125
- console.error(`${YELLOW} Your version:${RESET} ${RED}${CURRENT_NODE_VERSION}${RESET}`);
126
- console.error(`${YELLOW} Required:${RESET} ${CYAN}≥${MIN_NODE_VERSION}${RESET} (Node.js 22 LTS recommended)`);
127
- console.error('');
128
- console.error(`${DIM} Why? SpecWeave uses modern JavaScript features (ES2022+) including${RESET}`);
129
- console.error(`${DIM} import assertions which require Node.js 20.12.0+${RESET}`);
130
- console.error('');
131
- console.error(`${BOLD}Quick upgrade:${RESET}`);
132
- console.error(getUpgradeInstructions());
133
- console.error('');
134
- console.error(`${BOLD}Full guide:${RESET}`);
135
- console.error(` ${CYAN}${UNDERLINE}https://spec-weave.com/docs/guides/troubleshooting/common-errors#node-version-error${RESET}`);
136
- console.error('');
137
- console.error(`${DIM}After upgrading, verify with: node --version${RESET}`);
138
- console.error('');
139
- process.exit(1);
140
- }
141
-
142
- // ============================================================================
143
- // Node.js version is OK - proceed with normal imports
144
- // ============================================================================
10
+ import './check-node.js';
145
11
 
146
12
  import { Command } from 'commander';
147
13
  import chalk from 'chalk';
148
14
  import { createRequire } from 'module';
149
- import { fileURLToPath } from 'url';
150
- import { dirname } from 'path';
151
-
152
- // ESM equivalents for __dirname and __filename
153
- const __filename = fileURLToPath(import.meta.url);
154
- const __dirname = dirname(__filename);
155
15
 
156
16
  // For importing package.json (need createRequire in ESM)
157
17
  const require = createRequire(import.meta.url);
158
18
  const packageJson = require('../package.json');
159
19
 
160
- // ============================================================================
161
- // DEVELOPMENT GUARD: Check if dist/ is built (prevents silent hangs)
162
- // ============================================================================
163
- // This only matters for developers running from source. NPM users always get
164
- // a pre-built package via prepublishOnly hook.
165
- // ============================================================================
166
- import { existsSync } from 'fs';
167
- import { join } from 'path';
168
-
169
- const distCliPath = join(__dirname, '..', 'dist', 'src', 'cli', 'commands', 'init.js');
170
- const isDevEnvironment = existsSync(join(__dirname, '..', 'tsconfig.json'));
171
-
172
- if (isDevEnvironment && !existsSync(distCliPath)) {
173
- const RED = '\x1b[31m';
174
- const YELLOW = '\x1b[33m';
175
- const CYAN = '\x1b[36m';
176
- const BOLD = '\x1b[1m';
177
- const RESET = '\x1b[0m';
178
- const DIM = '\x1b[2m';
179
-
180
- console.error('');
181
- console.error(`${RED}${BOLD}╔══════════════════════════════════════════════════════════════════╗${RESET}`);
182
- console.error(`${RED}${BOLD}║ SpecWeave is not built! Run: npm run rebuild ║${RESET}`);
183
- console.error(`${RED}${BOLD}╚══════════════════════════════════════════════════════════════════╝${RESET}`);
184
- console.error('');
185
- console.error(`${YELLOW} Missing:${RESET} ${DIM}dist/src/cli/commands/init.js${RESET}`);
186
- console.error('');
187
- console.error(`${BOLD}Quick fix:${RESET}`);
188
- console.error(` ${CYAN}npm run rebuild${RESET}`);
189
- console.error('');
190
- console.error(`${DIM} This happens when 'npm run clean' runs without 'npm run build'.${RESET}`);
191
- console.error(`${DIM} NPM users never see this - packages are pre-built before publish.${RESET}`);
192
- console.error('');
193
- process.exit(1);
194
- }
20
+ import './check-build.js';
195
21
 
196
22
  const program = new Command();
197
23
 
@@ -559,7 +385,6 @@ program
559
385
  noPush: options.push === false, // Handle --no-push
560
386
  force: options.force,
561
387
  branch: options.branch,
562
- projectRoot: process.cwd()
563
388
  });
564
389
  });
565
390
 
@@ -954,6 +779,13 @@ program
954
779
  if (!result.success) process.exit(1);
955
780
  });
956
781
 
782
+ // Route lazy CLI actions through the guarded command factory. Keep registrations
783
+ // here so static shell-completion generation still sees every command and option.
784
+ async function runLspCommand(args) {
785
+ const { createLspCommand } = await import('../dist/src/cli/commands/lsp.js');
786
+ await createLspCommand().parseAsync(args, { from: 'user' });
787
+ }
788
+
957
789
  // LSP command - Code intelligence operations
958
790
  const lspCmd = program
959
791
  .command('lsp')
@@ -963,40 +795,35 @@ lspCmd
963
795
  .command('refs <file> <symbol>')
964
796
  .description('Find all references to a symbol')
965
797
  .action(async (file, symbol) => {
966
- const { handleLspRefs } = await import('../dist/src/cli/commands/lsp.js');
967
- await handleLspRefs(process.cwd(), file, symbol);
798
+ await runLspCommand(['refs', '--', file, symbol]);
968
799
  });
969
800
 
970
801
  lspCmd
971
802
  .command('def <file> <symbol>')
972
803
  .description('Go to definition of a symbol')
973
804
  .action(async (file, symbol) => {
974
- const { handleLspDef } = await import('../dist/src/cli/commands/lsp.js');
975
- await handleLspDef(process.cwd(), file, symbol);
805
+ await runLspCommand(['def', '--', file, symbol]);
976
806
  });
977
807
 
978
808
  lspCmd
979
809
  .command('hover <file> <symbol>')
980
810
  .description('Get type information for a symbol')
981
811
  .action(async (file, symbol) => {
982
- const { handleLspHover } = await import('../dist/src/cli/commands/lsp.js');
983
- await handleLspHover(process.cwd(), file, symbol);
812
+ await runLspCommand(['hover', '--', file, symbol]);
984
813
  });
985
814
 
986
815
  lspCmd
987
816
  .command('symbols <file>')
988
817
  .description('List all symbols in a file')
989
818
  .action(async (file) => {
990
- const { handleLspSymbols } = await import('../dist/src/cli/commands/lsp.js');
991
- await handleLspSymbols(process.cwd(), file);
819
+ await runLspCommand(['symbols', '--', file]);
992
820
  });
993
821
 
994
822
  lspCmd
995
823
  .command('search <query>')
996
824
  .description('Search for symbols in workspace')
997
825
  .action(async (query) => {
998
- const { handleLspSearch } = await import('../dist/src/cli/commands/lsp.js');
999
- await handleLspSearch(process.cwd(), query);
826
+ await runLspCommand(['search', '--', query]);
1000
827
  });
1001
828
 
1002
829
  lspCmd
@@ -1004,16 +831,14 @@ lspCmd
1004
831
  .description('Warm up LSP by pre-indexing workspace (run on session start)')
1005
832
  .option('--quiet', 'Suppress output')
1006
833
  .action(async (files, options) => {
1007
- const { handleLspWarmup } = await import('../dist/src/cli/commands/lsp.js');
1008
- await handleLspWarmup(process.cwd(), files, options.quiet ?? false);
834
+ await runLspCommand(['warmup', ...(options.quiet ? ['--quiet'] : []), '--', ...files]);
1009
835
  });
1010
836
 
1011
837
  lspCmd
1012
838
  .command('status')
1013
839
  .description('Show LSP status and warm-up state')
1014
840
  .action(async () => {
1015
- const { handleLspStatus } = await import('../dist/src/cli/commands/lsp.js');
1016
- await handleLspStatus(process.cwd());
841
+ await runLspCommand(['status']);
1017
842
  });
1018
843
 
1019
844
  lspCmd
@@ -1024,13 +849,10 @@ lspCmd
1024
849
  .option('--dry-run', 'Show what would be installed without installing')
1025
850
  .option('--scope <scope>', 'Installation scope: user, project, local', 'project')
1026
851
  .action(async (options) => {
1027
- const { handleLspSetup } = await import('../dist/src/cli/commands/lsp.js');
1028
- await handleLspSetup(process.cwd(), {
1029
- maxLanguages: parseInt(options.max, 10),
1030
- minFileCount: parseInt(options.minFiles, 10),
1031
- dryRun: options.dryRun ?? false,
1032
- scope: options.scope,
1033
- });
852
+ await runLspCommand([
853
+ 'setup', '--max', options.max, '--min-files', options.minFiles,
854
+ '--scope', options.scope, ...(options.dryRun ? ['--dry-run'] : []),
855
+ ]);
1034
856
  });
1035
857
 
1036
858
  // Commits command - Display last 2 git commits
@@ -1537,114 +1359,13 @@ program
1537
1359
  });
1538
1360
  });
1539
1361
 
1540
- // Help text
1541
- program.on('--help', () => {
1542
- console.log('');
1543
- console.log('Examples:');
1544
- console.log(' $ specweave init my-saas # Create new project (auto-detect tool)');
1545
- console.log(' $ specweave init my-saas --adapter cursor # Create project for Cursor');
1546
- console.log(' $ specweave init my-saas --language ru # Create project with Russian language');
1547
- console.log(' $ specweave install pm --local # Install PM agent locally');
1548
- console.log(' $ specweave install --global # Install all (interactive)');
1549
- console.log(' $ specweave list # List all available components');
1550
- console.log(' $ specweave list --installed # Show installed components');
1551
- console.log(' $ specweave status # Show all increments status');
1552
- console.log(' $ specweave status --verbose # Show detailed increment info');
1553
- console.log(' $ specweave status-line # Display current increment progress');
1554
- console.log(' $ specweave status-line --json # Output progress as JSON');
1555
- console.log(' $ specweave pause 0007 --reason "blocked" # Pause increment 0007');
1556
- console.log(' $ specweave resume 0007 # Resume increment 0007');
1557
- console.log(' $ specweave abandon 0007 --reason "obsolete" # Abandon increment 0007');
1558
- console.log(' $ specweave qa 0008 # Quick quality check');
1559
- console.log(' $ specweave qa 0008 --pre # Pre-implementation check');
1560
- console.log(' $ specweave qa 0008 --gate --export # Quality gate + export to tasks');
1561
- console.log(' $ specweave sync status # Token/account, provider health, sync gaps');
1562
- console.log(' $ specweave jobs # Show active background jobs');
1563
- console.log(' $ specweave jobs --follow <jobId> # Follow job progress live');
1564
- console.log(' $ specweave jobs --logs <jobId> # View worker logs');
1565
- console.log(' $ specweave jobs --resume <jobId> # Resume paused job');
1566
- console.log(' $ specweave living-docs # Launch Living Docs (interactive)');
1567
- console.log(' $ specweave living-docs --depth deep-native # AI-powered analysis (FREE w/ MAX)');
1568
- console.log(' $ specweave living-docs --full-scan # Full deep scan (all phases)');
1569
- console.log(' $ specweave living-docs --resume <jobId> # Resume orphaned job');
1570
- console.log(' $ specweave sync push 0008 # Push increment progress to GitHub/Jira/ADO');
1571
- console.log(' $ specweave sync pull --since 3 # Show external changes from the last 3 days');
1572
- console.log(' $ specweave cache # Show cache status');
1573
- console.log(' $ specweave cache --rebuild # Rebuild dashboard cache');
1574
- console.log(' $ specweave cache --debug # Show cache debug info');
1575
- console.log(' $ specweave sync setup --validate # Validate tracker configuration + credentials');
1576
- console.log(' $ specweave docs # Preview internal docs (port 3015)');
1577
- console.log(' $ specweave docs public # Preview public docs (port 3016)');
1578
- console.log(' $ specweave docs build # Build internal site');
1579
- console.log(' $ specweave docs build --scope public # Build public site');
1580
- console.log(' $ specweave docs validate # Check for docs errors');
1581
- console.log(' $ specweave docs status # Show docs status');
1582
- console.log(' $ specweave docs kill # Stop all docs servers');
1583
- console.log(' $ specweave doctor --fix-status # Fix metadata/spec status desyncs');
1584
- console.log(' $ specweave refresh-plugins # Refresh core SpecWeave plugin');
1585
- console.log(' $ specweave refresh-plugins --all # Refresh every installed plugin');
1586
- console.log(' $ specweave refresh-plugins --force # Force reinstall (skip hash check)');
1587
- console.log(' $ specweave update # Update CLI + instructions + config');
1588
- console.log(' $ specweave update --plugins # Also refresh marketplace plugins');
1589
- console.log(' $ specweave update --no-self # Skip CLI update, only project files');
1590
- console.log(' $ specweave update --check # Dry run - preview changes');
1591
- console.log('');
1592
- console.log('Plugin Management (use Claude CLI commands):');
1593
- console.log(' $ claude plugin install sw@specweave # Install core SpecWeave');
1594
- console.log(' $ claude plugin list # Show installed plugins');
1595
- console.log(' $ vskill install anton-abyzov/vskill --plugin mobile # Install domain plugin');
1596
- console.log('');
1597
- console.log('Supported AI Tools:');
1598
- console.log(' - Claude Code (full automation) - Native skills, agents, hooks');
1599
- console.log(' - Cursor (semi-automation) - .cursorrules, @ shortcuts');
1600
- console.log(' - GitHub Copilot (basic) - Workspace instructions');
1601
- console.log(' - Generic (manual) - Works with ANY AI (ChatGPT, Gemini, etc.)');
1602
- console.log('');
1603
- console.log('For more information, visit: https://spec-weave.com');
1604
- });
1605
-
1606
- // Startup duplicate check (runs before any command)
1607
- async function checkForDuplicates() {
1608
- try {
1609
- // Skip check for init command (no .specweave yet)
1610
- const args = process.argv.slice(2);
1611
- if (args.length === 0 || args[0] === 'init' || args[0] === '--help' || args[0] === '-h' || args[0] === '--version' || args[0] === '-V') {
1612
- return;
1613
- }
1614
-
1615
- // Check if .specweave exists
1616
- const { default: fs } = await import('fs-extra');
1617
- const { default: path } = await import('path');
1618
- const specweavePath = path.join(process.cwd(), '.specweave');
1619
-
1620
- if (!fs.existsSync(specweavePath)) {
1621
- return; // No .specweave directory, skip check
1622
- }
1362
+ // Supplementary CLI help and project coordination.
1363
+ import { registerHelp } from './help.js';
1364
+ import { registerProjectCommand } from './project.js';
1365
+ registerHelp(program);
1366
+ registerProjectCommand(program);
1623
1367
 
1624
- // Detect duplicates
1625
- const { detectAllDuplicates } = await import('../dist/src/core/increment/duplicate-detector.js');
1626
- const report = await detectAllDuplicates(process.cwd());
1627
-
1628
- if (report.duplicateCount > 0) {
1629
- console.log(chalk.yellow('\n⚠️ Duplicate increment(s) detected:\n'));
1630
-
1631
- for (const duplicate of report.duplicates) {
1632
- console.log(chalk.dim(` ${duplicate.incrementNumber}:`));
1633
- for (const location of duplicate.locations) {
1634
- const indicator = location === duplicate.recommendedWinner ? chalk.green('→') : chalk.red('✗');
1635
- console.log(` ${indicator} ${location.name} [${location.status}]`);
1636
- }
1637
- }
1638
-
1639
- console.log(chalk.dim('\n Run sw:fix-duplicates to resolve\n'));
1640
- }
1641
- } catch (error) {
1642
- // Silently ignore errors (don't block CLI startup)
1643
- if (process.env.DEBUG) {
1644
- console.error(chalk.dim(`[DEBUG] Duplicate check failed: ${error}`));
1645
- }
1646
- }
1647
- }
1368
+ import { checkForDuplicates } from './startup-check.js';
1648
1369
 
1649
1370
  // Dashboard command - Real-time observability dashboard
1650
1371
  program
@@ -0,0 +1,44 @@
1
+ import chalk from 'chalk';
2
+ // Startup duplicate check (runs before any command)
3
+ export async function checkForDuplicates() {
4
+ try {
5
+ // Skip check for init command (no .specweave yet)
6
+ const args = process.argv.slice(2);
7
+ if (args.length === 0 || args[0] === 'init' || args[0] === '--help' || args[0] === '-h' || args[0] === '--version' || args[0] === '-V') {
8
+ return;
9
+ }
10
+
11
+ // Check if .specweave exists
12
+ const { default: fs } = await import('fs-extra');
13
+ const { default: path } = await import('path');
14
+ const specweavePath = path.join(process.cwd(), '.specweave');
15
+
16
+ if (!fs.existsSync(specweavePath)) {
17
+ return; // No .specweave directory, skip check
18
+ }
19
+
20
+ // Detect duplicates
21
+ const { detectAllDuplicates } = await import('../dist/src/core/increment/duplicate-detector.js');
22
+ const report = await detectAllDuplicates(process.cwd());
23
+
24
+ if (report.duplicateCount > 0) {
25
+ console.log(chalk.yellow('\n⚠️ Duplicate increment(s) detected:\n'));
26
+
27
+ for (const duplicate of report.duplicates) {
28
+ console.log(chalk.dim(` ${duplicate.incrementNumber}:`));
29
+ for (const location of duplicate.locations) {
30
+ const indicator = location === duplicate.recommendedWinner ? chalk.green('→') : chalk.red('✗');
31
+ console.log(` ${indicator} ${location.name} [${location.status}]`);
32
+ }
33
+ }
34
+
35
+ console.log(chalk.dim('\n Run sw:fix-duplicates to resolve\n'));
36
+ }
37
+ } catch (error) {
38
+ // Silently ignore errors (don't block CLI startup)
39
+ if (process.env.DEBUG) {
40
+ console.error(chalk.dim(`[DEBUG] Duplicate check failed: ${error}`));
41
+ }
42
+ }
43
+ }
44
+