specweave 1.0.472 → 1.0.474

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 (48) hide show
  1. package/CLAUDE.md +1 -1
  2. package/bin/specweave.js +21 -0
  3. package/dist/src/cli/commands/branch-name.d.ts +17 -0
  4. package/dist/src/cli/commands/branch-name.d.ts.map +1 -0
  5. package/dist/src/cli/commands/branch-name.js +47 -0
  6. package/dist/src/cli/commands/branch-name.js.map +1 -0
  7. package/dist/src/cli/commands/init.d.ts.map +1 -1
  8. package/dist/src/cli/commands/init.js +0 -1
  9. package/dist/src/cli/commands/init.js.map +1 -1
  10. package/dist/src/cli/commands/refresh-plugins.d.ts +6 -13
  11. package/dist/src/cli/commands/refresh-plugins.d.ts.map +1 -1
  12. package/dist/src/cli/commands/refresh-plugins.js +14 -38
  13. package/dist/src/cli/commands/refresh-plugins.js.map +1 -1
  14. package/dist/src/cli/commands/sync-health.d.ts +34 -0
  15. package/dist/src/cli/commands/sync-health.d.ts.map +1 -0
  16. package/dist/src/cli/commands/sync-health.js +175 -0
  17. package/dist/src/cli/commands/sync-health.js.map +1 -0
  18. package/dist/src/cli/commands/sync-setup.d.ts.map +1 -1
  19. package/dist/src/cli/commands/sync-setup.js +15 -1
  20. package/dist/src/cli/commands/sync-setup.js.map +1 -1
  21. package/dist/src/cli/helpers/init/plugin-installer.d.ts +10 -10
  22. package/dist/src/cli/helpers/init/plugin-installer.d.ts.map +1 -1
  23. package/dist/src/cli/helpers/init/plugin-installer.js +52 -197
  24. package/dist/src/cli/helpers/init/plugin-installer.js.map +1 -1
  25. package/dist/src/config/types.d.ts +2 -2
  26. package/dist/src/core/cicd/branch-utils.d.ts +29 -0
  27. package/dist/src/core/cicd/branch-utils.d.ts.map +1 -0
  28. package/dist/src/core/cicd/branch-utils.js +35 -0
  29. package/dist/src/core/cicd/branch-utils.js.map +1 -0
  30. package/dist/src/core/cicd/config-loader.d.ts.map +1 -1
  31. package/dist/src/core/cicd/config-loader.js.map +1 -1
  32. package/dist/src/core/config/types.d.ts +2 -0
  33. package/dist/src/core/config/types.d.ts.map +1 -1
  34. package/dist/src/core/config/types.js +1 -0
  35. package/dist/src/core/config/types.js.map +1 -1
  36. package/dist/src/core/lazy-loading/llm-plugin-detector.d.ts +18 -47
  37. package/dist/src/core/lazy-loading/llm-plugin-detector.d.ts.map +1 -1
  38. package/dist/src/core/lazy-loading/llm-plugin-detector.js +41 -409
  39. package/dist/src/core/lazy-loading/llm-plugin-detector.js.map +1 -1
  40. package/dist/src/init/research/types.d.ts +1 -1
  41. package/dist/src/utils/plugin-copier.d.ts +14 -0
  42. package/dist/src/utils/plugin-copier.d.ts.map +1 -1
  43. package/dist/src/utils/plugin-copier.js +140 -1
  44. package/dist/src/utils/plugin-copier.js.map +1 -1
  45. package/package.json +1 -1
  46. package/plugins/specweave/hooks/user-prompt-submit.sh +14 -291
  47. package/plugins/specweave/skills/team-lead/SKILL.md +43 -39
  48. package/plugins/specweave/skills/team-merge/SKILL.md +51 -33
@@ -17,7 +17,6 @@ import * as os from 'os';
17
17
  import * as fs from 'fs';
18
18
  import * as path from 'path';
19
19
  import { consoleLogger as logger } from '../../utils/logger.js';
20
- import { resolveVskillPath as _resolveVskillPath, resolveSpecweaveDir as _resolveSpecweaveDir } from '../../utils/vskill-resolver.js';
21
20
  import { getProjectRoot } from '../../utils/find-project-root.js';
22
21
  // IMPORTANT: Use canonical Claude CLI detection from utils (handles shell functions, nvm, etc.)
23
22
  import { detectClaudeCli, getCleanEnv } from '../../utils/claude-cli-detector.js';
@@ -127,47 +126,13 @@ export const SPECWEAVE_PLUGINS = [
127
126
  'sw-docs', // SpecWeave docs
128
127
  'sw-media', // AI image/video generation
129
128
  ];
130
- /**
131
- * Domain skill plugins in the vskill marketplace.
132
- *
133
- * Each category is a standalone plugin (e.g., `frontend@vskill`, `backend@vskill`).
134
- * Skills are invoked as `plugin:skill` (e.g., `frontend:nextjs`, `backend:dotnet`).
135
- *
136
- * v2.1.0: Split from monolithic `vs` plugin into per-category plugins for granularity.
137
- */
138
- export const VSKILL_PLUGINS = [
139
- 'mobile', // React Native, iOS, Android, Expo, app store publishing
140
- 'skills', // Skill discovery — find and install skills
141
- ];
142
- /**
143
- * Plugins that are planned but not yet available (no directory on disk).
144
- * Kept here so the LLM prompt can inform users these are not yet installable.
145
- * v1.0.397: Removed from VSKILL_PLUGINS to prevent suggesting non-existent plugins.
146
- */
147
- export const VSKILL_PLUGINS_PLANNED = [
148
- 'frontend', // React, Vue, Angular, Next.js, UI components [NOT YET AVAILABLE]
149
- 'backend', // Java Spring Boot, Rust Axum [NOT YET AVAILABLE]
150
- 'testing', // Jest, Vitest, Playwright, E2E [NOT YET AVAILABLE]
151
- 'infra', // Terraform, AWS, Azure, GCP, Docker, CI/CD [NOT YET AVAILABLE]
152
- 'k8s', // K8s, Helm, pods, deployments [NOT YET AVAILABLE]
153
- 'payments', // Stripe, PayPal, checkout [NOT YET AVAILABLE]
154
- 'ml', // Machine learning, PyTorch, TensorFlow [NOT YET AVAILABLE]
155
- 'kafka', // Apache Kafka, event streaming, n8n [NOT YET AVAILABLE]
156
- 'confluent', // Confluent Cloud, Schema Registry, ksqlDB [NOT YET AVAILABLE]
157
- 'cost', // Cloud cost optimization [NOT YET AVAILABLE]
158
- 'docs', // Extended documentation [NOT YET AVAILABLE]
159
- 'security', // Security scanning and hardening [NOT YET AVAILABLE]
160
- 'blockchain', // Web3, Solidity, smart contracts [NOT YET AVAILABLE]
161
- ];
162
- /** @deprecated Use VSKILL_PLUGINS */
163
- export const VSKILL_CATEGORIES = VSKILL_PLUGINS;
164
129
  /**
165
130
  * Combined list of all known plugins for validation.
166
- * Includes specweave plugins and vskill marketplace plugins.
131
+ * Only specweave plugins vskill marketplace plugins have been removed (v1.0.533).
167
132
  */
168
- export const ALL_KNOWN_PLUGINS = [...SPECWEAVE_PLUGINS, ...VSKILL_PLUGINS];
133
+ export const ALL_KNOWN_PLUGINS = [...SPECWEAVE_PLUGINS];
169
134
  /**
170
- * All valid plugins — specweave plugins and vskill plugins.
135
+ * All valid plugins — only specweave plugins (v1.0.533: vskill removed).
171
136
  */
172
137
  export const ALL_VALID_PLUGINS = ALL_KNOWN_PLUGINS;
173
138
  /**
@@ -177,27 +142,11 @@ export function isSpecWeavePlugin(plugin) {
177
142
  return SPECWEAVE_PLUGINS.includes(plugin);
178
143
  }
179
144
  /**
180
- * Check if a plugin is a vskill marketplace plugin.
181
- */
182
- export function isVskillPlugin(plugin) {
183
- return VSKILL_PLUGINS.includes(plugin);
184
- }
185
- /**
186
- * Check if a plugin is any known plugin (specweave or vskill).
145
+ * Check if a plugin is any known plugin (specweave only, v1.0.533).
187
146
  */
188
147
  export function isKnownPlugin(plugin) {
189
148
  return ALL_KNOWN_PLUGINS.includes(plugin);
190
149
  }
191
- /**
192
- * Get the marketplace name for a plugin.
193
- * Returns 'specweave' for sw-* plugins, 'vskill' for domain skills.
194
- */
195
- export function getPluginMarketplace(plugin) {
196
- if (isVskillPlugin(plugin)) {
197
- return 'vskill';
198
- }
199
- return 'specweave';
200
- }
201
150
  // Cache the CLI detection result for performance (detect once per process)
202
151
  let cachedCliStatus = null;
203
152
  /**
@@ -278,30 +227,27 @@ export function isClaudeCliAvailable() {
278
227
  */
279
228
  function buildDetectionPrompt() {
280
229
  return `You detect which plugins to load based on the user's prompt.
281
- Return specweave (sw-*) or vskill domain plugin names.
230
+ Return specweave (sw-*) plugin names ONLY.
282
231
 
283
232
  DETECTION RULES:
284
- 1. EXPLICIT tech - user says "React" → frontend, ".NET" → backend
285
- 2. IMPLIED - "dashboard" needs API → backend
286
- 3. Questions/discussions ZERO plugins
287
- 4. ONLY suggest @specweave plugins (sw-*) for workflow/integrations, or vskill plugins for domain skills
233
+ 1. EXPLICIT mention of integrations - "GitHub sync" → sw-github, "JIRA" → sw-jira
234
+ 2. Questions/discussions ZERO plugins
235
+ 3. ONLY suggest @specweave plugins (sw-*)
236
+ 4. Domain plugins (frontend, backend, testing, etc.) are NOT available do NOT suggest them
288
237
 
289
238
  OUTPUT FORMAT (JSON only):
290
- {"plugins":["frontend"],"confidence":0.9,"reasoning":"one-line"}
239
+ {"plugins":["sw-github"],"confidence":0.9,"reasoning":"one-line"}
291
240
 
292
241
  ═══════════════════════════════════════════════════════════════
293
- PLUGINS - Use specweave (sw-*) or vskill domain plugin names
242
+ AVAILABLE PLUGINS (specweave only sw-*)
294
243
  ═══════════════════════════════════════════════════════════════
295
244
 
296
- mobile: React Native, iOS, Android, Expo, Flutter (ONLY if explicit)
297
- scout: find skill, discover skill, what skills available, search registry, install a skill, recommend skills, browse skills, vskill, skill for, which skill, explore skills (ONLY if asking about finding/discovering skills — NOT for domain work)
298
- sw-media: AI image generation, AI video generation, Remotion, text-to-image, text-to-video, Imagen, Veo, generate image, generate video, create video, media generation, Pollinations (ONLY if explicit)
299
-
300
- [NOT YET AVAILABLE — DO NOT suggest these plugins, they are planned but not installable]:
301
- frontend, backend, testing, infra, k8s, payments, ml, kafka, confluent, security, blockchain
302
- sw-github: GitHub issues, PRs, Actions, sync
245
+ sw-github: GitHub issues, PRs, Actions, sync (ONLY if explicit)
303
246
  sw-jira: JIRA, Atlassian (ONLY if explicit)
304
247
  sw-ado: Azure DevOps, work items (ONLY if explicit)
248
+ sw-media: AI image generation, AI video generation, Remotion, text-to-image, text-to-video, Imagen, Veo, generate image, generate video, create video, media generation, Pollinations (ONLY if explicit)
249
+
250
+ DO NOT suggest: frontend, backend, testing, infra, k8s, mobile, skills, payments, ml, kafka, confluent, security, blockchain — these are NOT available as plugins.
305
251
 
306
252
  ═══════════════════════════════════════════════════════════════
307
253
  INCREMENT RECOMMENDATION (v1.0.241 - DEFAULT: create increment)
@@ -369,17 +315,14 @@ EXPLICIT OPT-OUT → action: "none":
369
315
  - "just a quick fix", "without tracking", "already tracking"
370
316
 
371
317
  ═══════════════════════════════════════════════════════════════
372
- EXAMPLES (one per action type — keep prompt size minimal)
318
+ EXAMPLES
373
319
  ═══════════════════════════════════════════════════════════════
374
320
 
375
- "Build a React Native mobile app with app store publishing"
376
- {"plugins":["mobile"],"confidence":0.95,"reasoning":"React Nativemobile","increment":{"action":"new","confidence":0.95,"mandatory":true,"suggestedName":"react-native-mobile-app","reasoning":"Multi-component mobile feature"}}
321
+ "Sync our GitHub issues"
322
+ {"plugins":["sw-github"],"confidence":0.95,"reasoning":"GitHub syncsw-github","increment":{"action":"new","confidence":0.9,"mandatory":false,"suggestedName":"sync-github-issues","reasoning":"GitHub integration work"}}
377
323
 
378
324
  "The auth feature is broken again"
379
- {"plugins":[],"confidence":0.7,"reasoning":"No specific tech mentioned","increment":{"action":"reopen","confidence":0.8,"mandatory":false,"relatedKeyword":"auth","reasoning":"Related to previous auth work"}}
380
-
381
- "Urgent: production mobile app is crashing"
382
- {"plugins":["mobile"],"confidence":0.9,"reasoning":"Mobile app issue","increment":{"action":"hotfix","confidence":0.95,"mandatory":true,"suggestedName":"mobile-crash-hotfix","reasoning":"Production issue"}}
325
+ {"plugins":[],"confidence":0.7,"reasoning":"No specific integration mentioned","increment":{"action":"reopen","confidence":0.8,"mandatory":false,"relatedKeyword":"auth","reasoning":"Related to previous auth work"}}
383
326
 
384
327
  "Fix typo in README"
385
328
  {"plugins":[],"confidence":0.9,"reasoning":"Typo fix","increment":{"action":"small_fix","confidence":0.9,"mandatory":false,"suggestedName":"fix-readme-typo","reasoning":"Trivial 1-line change"}}
@@ -390,65 +333,6 @@ EXAMPLES (one per action type — keep prompt size minimal)
390
333
  "Investigate why the API sync keeps failing across multiple services"
391
334
  {"plugins":[],"confidence":0.8,"reasoning":"Investigation/debugging work","increment":{"action":"new","confidence":0.85,"mandatory":false,"suggestedName":"investigate-api-sync-failure","reasoning":"Multi-component investigation requiring structured tracking"}}
392
335
 
393
- ═══════════════════════════════════════════════════════════════
394
- SKILL INVOCATION (v2.1.0 - tell Claude which plugin:skill to use)
395
- ═══════════════════════════════════════════════════════════════
396
-
397
- ALSO specify which skill Claude SHOULD invoke for this task.
398
- Skills use "plugin:skill" format (e.g., "mobile:react-native", "mobile:appstore").
399
-
400
- "skillInvocation" field with:
401
- - skill: full skill name as plugin:skill (e.g., "mobile:react-native", "mobile:appstore")
402
- - reason: why this skill should be used
403
- - mandatory: true if Claude MUST use this skill, false if optional
404
-
405
- ⚠️ IMPORTANT: DO NOT suggest *-lsp plugins - they are BROKEN in official marketplace!
406
- LSP is handled separately via boostvolt/claude-code-lsps + ENABLE_LSP_TOOL=1 env var.
407
-
408
- SKILL CATALOG (use exact plugin:skill names — ONLY suggest skills from AVAILABLE plugins):
409
- mobile: mobile:appstore, mobile:capacitor, mobile:deep-linking, mobile:expo, mobile:flutter, mobile:jetpack, mobile:react-native, mobile:swiftui, mobile:testing
410
- skills: skills:scout
411
-
412
- [NOT YET AVAILABLE — DO NOT suggest these skills]:
413
- frontend, backend, testing, infra, k8s, ml, kafka, confluent, payments, docs, cost, security, blockchain
414
-
415
- SKILL INVOCATION RULES (pick the most specific skill):
416
- - .NET/C# → backend:dotnet MANDATORY
417
- - Go/Golang → backend:go MANDATORY
418
- - Python/FastAPI/Django → backend:python MANDATORY
419
- - Java/Spring → backend:java-spring MANDATORY
420
- - Rust → backend:rust MANDATORY
421
- - Node.js/Express/NestJS → backend:nodejs MANDATORY
422
- - GraphQL → backend:graphql MANDATORY
423
- - Next.js → frontend:nextjs MANDATORY
424
- - React/Vue/Angular → frontend:frontend-core MANDATORY
425
- - Figma design → frontend:figma MANDATORY
426
- - ML/AI → ml:engineer MANDATORY
427
- - Stripe/PayPal → payments:payment-core MANDATORY
428
- - Unit testing → testing:unit MANDATORY
429
- - E2E testing → testing:e2e MANDATORY
430
- - React Native → mobile:react-native MANDATORY
431
- - Flutter → mobile:flutter MANDATORY
432
- - SwiftUI/iOS → mobile:swiftui MANDATORY
433
- - Jetpack/Android → mobile:jetpack MANDATORY
434
- - Expo → mobile:expo MANDATORY
435
- - Terraform → infra:terraform MANDATORY
436
- - AWS → infra:aws MANDATORY
437
- - Azure → infra:azure MANDATORY
438
- - GCP → infra:gcp MANDATORY
439
- - GitHub Actions → infra:github-actions MANDATORY
440
- - Kubernetes → k8s:manifests recommended
441
- - Architecture → frontend:architect or relevant architect skill recommended
442
- - DO NOT suggest *-lsp plugins (broken in marketplace)
443
-
444
- SKILL EXAMPLES:
445
-
446
- "Build Spring Boot API with JPA"
447
- {"plugins":["backend"],"confidence":0.95,"reasoning":"Spring Boot→backend","increment":{"action":"new","confidence":0.9,"mandatory":true,"suggestedName":"spring-boot-api","reasoning":"New API"},"skillInvocation":{"skill":"backend:java-spring","reason":"Spring Boot patterns and JPA","mandatory":true}}
448
-
449
- "Write unit tests for the auth service"
450
- {"plugins":["testing"],"confidence":0.95,"reasoning":"Unit testing","increment":{"action":"small_fix","confidence":0.7,"mandatory":false,"reasoning":"Testing extends existing work"},"skillInvocation":{"skill":"testing:unit","reason":"Vitest/Jest patterns and TDD","mandatory":true}}
451
-
452
336
  ═══════════════════════════════════════════════════════════════
453
337
  LSP OPERATION DETECTION (v1.0.198 - unified detection)
454
338
  ═══════════════════════════════════════════════════════════════
@@ -470,7 +354,7 @@ LSP EXAMPLES:
470
354
  {"plugins":[],"confidence":0.95,"reasoning":"Code navigation","lsp":{"needed":true,"operation":"references","language":"typescript","warmupRequired":true}}
471
355
 
472
356
  "Build a React dashboard" (NO LSP needed)
473
- {"plugins":["frontend"],"confidence":0.95,"reasoning":"React development"}`;
357
+ {"plugins":[],"confidence":0.95,"reasoning":"React development"}`;
474
358
  }
475
359
  /**
476
360
  * Execute Claude CLI command safely
@@ -849,30 +733,6 @@ Which plugins should be loaded?`;
849
733
  return createFailureResult(startTime, `Detection failed: ${errorMsg}`);
850
734
  }
851
735
  }
852
- /**
853
- * Check if a plugin is already installed via vskill lockfile
854
- *
855
- * Reads vskill.lock from cwd and checks if the plugin has an entry.
856
- * This provides a fast-path to skip installation when plugin is
857
- * already present with a matching hash.
858
- *
859
- * @param pluginName - Name of the plugin to check
860
- * @returns true if plugin is in the lockfile
861
- */
862
- function isPluginInVskillLock(pluginName) {
863
- try {
864
- const lockPath = path.join(getProjectRoot(), 'vskill.lock');
865
- if (!fs.existsSync(lockPath)) {
866
- return false;
867
- }
868
- const content = fs.readFileSync(lockPath, 'utf-8');
869
- const lock = JSON.parse(content);
870
- return lock.skills && pluginName in lock.skills;
871
- }
872
- catch {
873
- return false;
874
- }
875
- }
876
736
  /** Track which plugins have already been reported this session (daily dedup) */
877
737
  const _reportedPlugins = new Set();
878
738
  /**
@@ -900,23 +760,8 @@ async function reportInstallsForPlugin(pluginName) {
900
760
  .filter(d => d.isDirectory() && fs.existsSync(path.join(skillsDir, d.name, 'SKILL.md')));
901
761
  if (skillDirs.length === 0)
902
762
  return;
903
- // Read repoUrl from lockfile
904
- let repoUrl;
905
- try {
906
- const lockPath = path.join(projectRoot, 'vskill.lock');
907
- const lock = JSON.parse(fs.readFileSync(lockPath, 'utf-8'));
908
- const entry = lock.skills?.[pluginName];
909
- if (entry?.source) {
910
- // source format: "github:owner/repo#plugin:name" → extract "owner/repo"
911
- const match = entry.source.match(/github:([^#]+)/);
912
- if (match)
913
- repoUrl = match[1];
914
- }
915
- }
916
- catch { /* best-effort */ }
917
763
  const skills = skillDirs.map(d => ({
918
764
  skillName: d.name,
919
- ...(repoUrl ? { repoUrl } : {}),
920
765
  }));
921
766
  const controller = new AbortController();
922
767
  const timeout = setTimeout(() => controller.abort(), 5000);
@@ -940,202 +785,41 @@ async function reportInstallsForPlugin(pluginName) {
940
785
  // Silent — install tracking must never block plugin loading
941
786
  }
942
787
  }
943
- /** Resolve vskill path from this module's location */
944
- function resolveVskillCliPath() {
945
- return _resolveVskillPath(__dirname);
946
- }
947
- /** Resolve specweave source directory */
948
- function resolveSpecweaveDir() {
949
- return _resolveSpecweaveDir(__dirname);
950
- }
951
788
  /**
952
- * Install a specweave local plugin via vskill install with --plugin-dir
953
- * (v1.0.343: fixed 'add' → 'install' to match vskill CLI)
789
+ * Install a plugin using native Claude plugin system.
954
790
  *
955
- * @param pluginName - Name of the sw-* plugin to install
956
- * @param timeout - Timeout in milliseconds
957
- * @returns Installation result
958
- */
959
- async function installSpecweaveLocalPlugin(pluginName, timeout) {
960
- try {
961
- const vskillPath = resolveVskillCliPath();
962
- const pluginDir = resolveSpecweaveDir();
963
- const result = spawnSync('node', [
964
- vskillPath,
965
- 'install',
966
- '--plugin-dir', pluginDir,
967
- '--plugin', pluginName,
968
- '--force', // Auto-accept scan results during lazy loading
969
- '--yes',
970
- ], {
971
- encoding: 'utf8',
972
- timeout,
973
- maxBuffer: 1024 * 1024,
974
- windowsHide: true,
975
- cwd: process.cwd(),
976
- });
977
- if (result.error) {
978
- return { success: false, plugin: pluginName, error: `Install error: ${result.error.message}` };
979
- }
980
- const stdout = result.stdout || '';
981
- const stderr = result.stderr || '';
982
- const combined = `${stdout} ${stderr}`.toLowerCase();
983
- if (combined.includes('already')) {
984
- return { success: true, plugin: pluginName, alreadyInstalled: true };
985
- }
986
- if (result.status === 0) {
987
- return { success: true, plugin: pluginName };
988
- }
989
- return { success: false, plugin: pluginName, error: stderr || stdout || `Exit code ${result.status}` };
990
- }
991
- catch (error) {
992
- return { success: false, plugin: pluginName, error: `Install failed: ${error}` };
993
- }
994
- }
995
- /**
996
- * Install a vskill repo plugin via vskill install --repo
997
- * (v1.0.343: fixed 'add' → 'install' to match vskill CLI)
998
- *
999
- * v2.1.0: Per-category plugins in vskill marketplace (frontend, backend, etc.).
1000
- * Uses: vskill install --repo anton-abyzov/vskill --plugin <name> --force --yes
1001
- *
1002
- * @param pluginName - Name of the vskill plugin (e.g., "frontend", "backend")
1003
- * @param timeout - Timeout in milliseconds
1004
- * @returns Installation result
1005
- */
1006
- async function installVskillRepoPlugin(pluginName, timeout, skillFilter) {
1007
- try {
1008
- const vskillPath = resolveVskillCliPath();
1009
- const args = [
1010
- vskillPath,
1011
- 'install',
1012
- '--repo', 'anton-abyzov/vskill',
1013
- '--plugin', pluginName,
1014
- '--force',
1015
- '--yes',
1016
- ];
1017
- // Filter skills within the plugin to only install relevant ones
1018
- if (skillFilter) {
1019
- args.push('--only-skills', skillFilter);
1020
- logger.debug(`Installing ${pluginName} with skill filter: ${skillFilter}`);
1021
- }
1022
- const result = spawnSync('node', args, {
1023
- encoding: 'utf8',
1024
- timeout,
1025
- maxBuffer: 1024 * 1024,
1026
- windowsHide: true,
1027
- cwd: process.cwd(),
1028
- });
1029
- if (result.error) {
1030
- return { success: false, plugin: pluginName, error: `Install error: ${result.error.message}` };
1031
- }
1032
- const stdout = result.stdout || '';
1033
- const stderr = result.stderr || '';
1034
- const combined = `${stdout} ${stderr}`.toLowerCase();
1035
- if (combined.includes('already')) {
1036
- return { success: true, plugin: pluginName, alreadyInstalled: true };
1037
- }
1038
- if (result.status === 0) {
1039
- return { success: true, plugin: pluginName };
1040
- }
1041
- return { success: false, plugin: pluginName, error: stderr || stdout || `Exit code ${result.status}` };
1042
- }
1043
- catch (error) {
1044
- return { success: false, plugin: pluginName, error: `Install failed: ${error}` };
1045
- }
1046
- }
1047
- /**
1048
- * Install a plugin using vskill (routes to correct installer)
1049
- *
1050
- * v2.1.0: Routes to installSpecweaveLocalPlugin for sw-* plugins,
1051
- * or installVskillRepoPlugin for vskill domain plugins.
1052
- *
1053
- * Fast-path: If plugin is already in vskill.lock, skip installation.
791
+ * @deprecated v1.0.535: On-demand plugin installation removed.
792
+ * All plugins are now installed at init time via direct file copy
793
+ * to .claude/skills/. This function is a no-op that returns success.
1054
794
  *
1055
795
  * @param pluginName - Name of the plugin to install
1056
- * @param timeout - Timeout in milliseconds
1057
- * @returns Installation result
796
+ * @param timeout - Timeout in milliseconds (unused)
797
+ * @returns Installation result (always success/alreadyInstalled)
1058
798
  */
1059
799
  export async function installPluginViaCli(pluginName, timeout = 30000, skillFilter) {
1060
- // v2.1.0: Accept both specweave and vskill plugins
1061
- if (!isKnownPlugin(pluginName)) {
1062
- return {
1063
- success: false,
1064
- plugin: pluginName,
1065
- error: `Unknown plugin: ${pluginName}. Only @specweave or vskill repo plugins are allowed.`,
1066
- };
1067
- }
1068
- // Check CLI availability (still needed for detect-intent etc.)
1069
- const cliStatus = isClaudeCliAvailable();
1070
- if (!cliStatus.available) {
1071
- return {
1072
- success: false,
1073
- plugin: pluginName,
1074
- error: cliStatus.error,
1075
- };
1076
- }
1077
- // Fast-path: Check vskill.lock - skip if already installed (works for both sources)
1078
- if (isPluginInVskillLock(pluginName)) {
1079
- logger.debug(`Plugin ${pluginName} already in vskill.lock, skipping installation`);
1080
- // Still report installs even on fast-path — specweave is long-lived so fire-and-forget is safe
1081
- reportInstallsForPlugin(pluginName).catch(() => { });
1082
- return {
1083
- success: true,
1084
- plugin: pluginName,
1085
- alreadyInstalled: true,
1086
- };
1087
- }
1088
- // Route to correct installer based on plugin source
1089
- if (isVskillPlugin(pluginName)) {
1090
- return installVskillRepoPlugin(pluginName, timeout, skillFilter);
1091
- }
1092
- return installSpecweaveLocalPlugin(pluginName, timeout);
800
+ // v1.0.535: No-op plugins are pre-installed at init time
801
+ return { success: true, plugin: pluginName, alreadyInstalled: true };
1093
802
  }
1094
803
  /**
1095
804
  * Install multiple plugins via CLI
1096
805
  *
806
+ * @deprecated v1.0.535: No-op — plugins are pre-installed at init time.
1097
807
  * @param plugins - Array of plugin names to install
1098
- * @returns Array of installation results
808
+ * @returns Array of installation results (all alreadyInstalled)
1099
809
  */
1100
810
  export async function installPluginsViaCli(plugins, skillInvocation) {
1101
- const results = [];
1102
- // Extract sub-skill filter from skillInvocation (e.g., "backend:dotnet" "dotnet")
1103
- let skillFilterMap;
1104
- if (skillInvocation?.skill && skillInvocation.skill.includes(':')) {
1105
- const [pluginPart, skillPart] = skillInvocation.skill.split(':');
1106
- if (pluginPart && skillPart) {
1107
- skillFilterMap = new Map([[pluginPart, skillPart]]);
1108
- logger.debug(`Skill filter from invocation: ${pluginPart} → only install ${skillPart}`);
1109
- }
1110
- }
1111
- for (const plugin of plugins) {
1112
- const skillFilter = skillFilterMap?.get(plugin);
1113
- const result = await installPluginViaCli(plugin, 30000, skillFilter);
1114
- results.push(result);
1115
- // Log progress
1116
- if (result.success) {
1117
- if (result.alreadyInstalled) {
1118
- logger.debug(`Plugin ${plugin} already installed`);
1119
- }
1120
- else {
1121
- logger.info(`Installed plugin: ${plugin}`);
1122
- }
1123
- }
1124
- else {
1125
- logger.warn(`Failed to install ${plugin}: ${result.error}`);
1126
- }
1127
- }
1128
- return results;
811
+ // v1.0.535: No-op — plugins are pre-installed at init time
812
+ return plugins.map(plugin => ({ success: true, plugin, alreadyInstalled: true }));
1129
813
  }
1130
814
  /**
1131
815
  * Full pipeline: detect plugins from prompt and optionally install them
1132
816
  *
1133
- * Respects .specweave/config.json pluginAutoLoad settings:
1134
- * - enabled: false skip detection entirely
1135
- * - suggestOnly: true detect but don't install, return suggestions
817
+ * @deprecated v1.0.535: Plugin installation removed. Detection still works
818
+ * for increment suggestions but no longer triggers installation.
819
+ * All plugins are pre-installed at init time via direct file copy.
1136
820
  *
1137
821
  * @param userPrompt - The user's prompt
1138
- * @returns Detection and installation results
822
+ * @returns Detection results (installations always empty)
1139
823
  */
1140
824
  export async function detectAndInstallPlugins(userPrompt) {
1141
825
  // Check config first
@@ -1154,28 +838,12 @@ export async function detectAndInstallPlugins(userPrompt) {
1154
838
  installations: [],
1155
839
  };
1156
840
  }
1157
- // Step 1: Detect needed plugins
841
+ // Step 1: Detect needed plugins (still used for increment suggestions)
1158
842
  const detection = await detectPluginsViaLLM(userPrompt);
1159
- if (!detection.success || detection.plugins.length === 0) {
1160
- return {
1161
- detection,
1162
- installations: [],
1163
- };
1164
- }
1165
- // Step 2: If suggestOnly mode, DON'T install - just return suggestions
1166
- if (config.suggestOnly) {
1167
- logger.info(`[detectAndInstallPlugins] Suggest-only mode: detected ${detection.plugins.join(', ')}`);
1168
- return {
1169
- detection,
1170
- installations: [],
1171
- suggestOnly: true,
1172
- };
1173
- }
1174
- // Step 3: Install detected plugins with skill-level filtering from LLM detection
1175
- const installations = await installPluginsViaCli(detection.plugins, detection.skillInvocation);
843
+ // v1.0.535: No installation — plugins are pre-installed at init time
1176
844
  return {
1177
845
  detection,
1178
- installations,
846
+ installations: [],
1179
847
  };
1180
848
  }
1181
849
  /**
@@ -1203,44 +871,8 @@ Plugin auto-loading is disabled. Install Claude CLI to enable automatic plugin d
1203
871
  // Don't show message for other errors (silent degradation)
1204
872
  }
1205
873
  else if (detection.plugins.length > 0) {
1206
- // SUGGEST-ONLY MODE: Show which plugins would help, but don't install
1207
- if (suggestOnly) {
1208
- const installCmds = detection.plugins
1209
- .map((p) => {
1210
- if (p.startsWith('sw-') || p === 'sw') {
1211
- return ` npx vskill install --repo anton-abyzov/specweave --plugin ${p} --agent claude-code`;
1212
- }
1213
- return ` npx vskill install --repo anton-abyzov/vskill --plugin ${p} --agent claude-code`;
1214
- })
1215
- .join('\n');
1216
- const reason = detection.reasoning ? `\nWhy: ${detection.reasoning}` : '';
1217
- output.systemMessage = `SpecWeave: Suggested plugins for this task: ${detection.plugins.join(', ')}${reason}
1218
-
1219
- To install:
1220
- ${installCmds}
1221
-
1222
- To enable auto-install: set "pluginAutoLoad": { "suggestOnly": false } in .specweave/config.json
1223
- After installing, restart Claude Code session to use new plugins.`;
1224
- return JSON.stringify(output);
1225
- }
1226
- // NORMAL MODE: Show what was installed
1227
- const installed = installations.filter((i) => i.success && !i.alreadyInstalled);
1228
- const alreadyInstalled = installations.filter((i) => i.alreadyInstalled);
1229
- const failed = installations.filter((i) => !i.success);
1230
- const parts = [];
1231
- if (installed.length > 0) {
1232
- parts.push(`Loaded: ${installed.map((i) => i.plugin).join(', ')}`);
1233
- }
1234
- if (alreadyInstalled.length > 0 && installed.length === 0) {
1235
- // Only mention already installed if nothing new was loaded
1236
- parts.push(`Using: ${alreadyInstalled.map((i) => i.plugin).join(', ')}`);
1237
- }
1238
- if (failed.length > 0) {
1239
- parts.push(`Failed: ${failed.map((i) => i.plugin).join(', ')}`);
1240
- }
1241
- if (parts.length > 0) {
1242
- output.systemMessage = `SpecWeave: ${parts.join(' | ')}`;
1243
- }
874
+ // v1.0.535: Plugin installation removed — plugins are pre-installed at init time.
875
+ // No need for suggest-only or normal install mode messages.
1244
876
  }
1245
877
  return JSON.stringify(output);
1246
878
  }