@skillsmith/cli 0.4.3 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/src/commands/audit.d.ts +19 -0
  3. package/dist/src/commands/audit.d.ts.map +1 -0
  4. package/dist/src/commands/audit.js +134 -0
  5. package/dist/src/commands/audit.js.map +1 -0
  6. package/dist/src/commands/audit.test.d.ts +8 -0
  7. package/dist/src/commands/audit.test.d.ts.map +1 -0
  8. package/dist/src/commands/audit.test.js +97 -0
  9. package/dist/src/commands/audit.test.js.map +1 -0
  10. package/dist/src/commands/author/init.d.ts.map +1 -1
  11. package/dist/src/commands/author/init.js +4 -9
  12. package/dist/src/commands/author/init.js.map +1 -1
  13. package/dist/src/commands/create.d.ts +42 -0
  14. package/dist/src/commands/create.d.ts.map +1 -0
  15. package/dist/src/commands/create.js +325 -0
  16. package/dist/src/commands/create.js.map +1 -0
  17. package/dist/src/commands/diff.d.ts +17 -0
  18. package/dist/src/commands/diff.d.ts.map +1 -0
  19. package/dist/src/commands/diff.js +191 -0
  20. package/dist/src/commands/diff.js.map +1 -0
  21. package/dist/src/commands/diff.test.d.ts +6 -0
  22. package/dist/src/commands/diff.test.d.ts.map +1 -0
  23. package/dist/src/commands/diff.test.js +275 -0
  24. package/dist/src/commands/diff.test.js.map +1 -0
  25. package/dist/src/commands/index.d.ts +5 -0
  26. package/dist/src/commands/index.d.ts.map +1 -1
  27. package/dist/src/commands/index.js +10 -1
  28. package/dist/src/commands/index.js.map +1 -1
  29. package/dist/src/commands/install-skill.d.ts.map +1 -1
  30. package/dist/src/commands/install-skill.js +10 -3
  31. package/dist/src/commands/install-skill.js.map +1 -1
  32. package/dist/src/commands/install.d.ts +13 -0
  33. package/dist/src/commands/install.d.ts.map +1 -0
  34. package/dist/src/commands/install.js +213 -0
  35. package/dist/src/commands/install.js.map +1 -0
  36. package/dist/src/commands/manage.d.ts.map +1 -1
  37. package/dist/src/commands/manage.js +71 -27
  38. package/dist/src/commands/manage.js.map +1 -1
  39. package/dist/src/commands/pin.d.ts +24 -0
  40. package/dist/src/commands/pin.d.ts.map +1 -0
  41. package/dist/src/commands/pin.js +123 -0
  42. package/dist/src/commands/pin.js.map +1 -0
  43. package/dist/src/commands/pin.test.d.ts +6 -0
  44. package/dist/src/commands/pin.test.d.ts.map +1 -0
  45. package/dist/src/commands/pin.test.js +206 -0
  46. package/dist/src/commands/pin.test.js.map +1 -0
  47. package/dist/src/commands/search.d.ts.map +1 -1
  48. package/dist/src/commands/search.js +43 -3
  49. package/dist/src/commands/search.js.map +1 -1
  50. package/dist/src/commands/sync.d.ts.map +1 -1
  51. package/dist/src/commands/sync.js +3 -2
  52. package/dist/src/commands/sync.js.map +1 -1
  53. package/dist/src/index.d.ts +2 -1
  54. package/dist/src/index.d.ts.map +1 -1
  55. package/dist/src/index.js +16 -3
  56. package/dist/src/index.js.map +1 -1
  57. package/dist/src/templates/changelog.md.template.d.ts +8 -0
  58. package/dist/src/templates/changelog.md.template.d.ts.map +1 -0
  59. package/dist/src/templates/changelog.md.template.js +19 -0
  60. package/dist/src/templates/changelog.md.template.js.map +1 -0
  61. package/dist/src/templates/index.d.ts +1 -0
  62. package/dist/src/templates/index.d.ts.map +1 -1
  63. package/dist/src/templates/index.js +1 -0
  64. package/dist/src/templates/index.js.map +1 -1
  65. package/dist/src/templates/readme.md.template.d.ts +1 -1
  66. package/dist/src/templates/readme.md.template.d.ts.map +1 -1
  67. package/dist/src/templates/readme.md.template.js +1 -1
  68. package/dist/src/templates/skill.md.template.d.ts +1 -1
  69. package/dist/src/templates/skill.md.template.d.ts.map +1 -1
  70. package/dist/src/templates/skill.md.template.js +2 -4
  71. package/dist/src/templates/skill.md.template.js.map +1 -1
  72. package/dist/src/utils/license-validation.js +1 -1
  73. package/dist/src/utils/license-validation.js.map +1 -1
  74. package/dist/src/utils/manifest.d.ts +46 -0
  75. package/dist/src/utils/manifest.d.ts.map +1 -0
  76. package/dist/src/utils/manifest.js +55 -0
  77. package/dist/src/utils/manifest.js.map +1 -0
  78. package/dist/src/utils/skill-name.d.ts +19 -0
  79. package/dist/src/utils/skill-name.d.ts.map +1 -0
  80. package/dist/src/utils/skill-name.js +26 -0
  81. package/dist/src/utils/skill-name.js.map +1 -0
  82. package/dist/src/utils/skills-directory.d.ts +12 -3
  83. package/dist/src/utils/skills-directory.d.ts.map +1 -1
  84. package/dist/src/utils/skills-directory.js +63 -7
  85. package/dist/src/utils/skills-directory.js.map +1 -1
  86. package/dist/tests/create.test.d.ts +5 -0
  87. package/dist/tests/create.test.d.ts.map +1 -0
  88. package/dist/tests/create.test.js +449 -0
  89. package/dist/tests/create.test.js.map +1 -0
  90. package/dist/tests/install-skill.test.js +9 -4
  91. package/dist/tests/install-skill.test.js.map +1 -1
  92. package/dist/tests/license-validation.test.d.ts +8 -0
  93. package/dist/tests/license-validation.test.d.ts.map +1 -0
  94. package/dist/tests/license-validation.test.js +186 -0
  95. package/dist/tests/license-validation.test.js.map +1 -0
  96. package/dist/tests/manage.test.js +84 -0
  97. package/dist/tests/manage.test.js.map +1 -1
  98. package/dist/tests/recommend-helpers.test.d.ts +9 -0
  99. package/dist/tests/recommend-helpers.test.d.ts.map +1 -0
  100. package/dist/tests/recommend-helpers.test.js +308 -0
  101. package/dist/tests/recommend-helpers.test.js.map +1 -0
  102. package/dist/tests/recommend-scoring.test.d.ts +8 -0
  103. package/dist/tests/recommend-scoring.test.d.ts.map +1 -0
  104. package/dist/tests/recommend-scoring.test.js +184 -0
  105. package/dist/tests/recommend-scoring.test.js.map +1 -0
  106. package/dist/tests/tool-analyzer.test.d.ts +8 -0
  107. package/dist/tests/tool-analyzer.test.d.ts.map +1 -0
  108. package/dist/tests/tool-analyzer.test.js +149 -0
  109. package/dist/tests/tool-analyzer.test.js.map +1 -0
  110. package/dist/tests/unit/commands/install.test.d.ts +7 -0
  111. package/dist/tests/unit/commands/install.test.d.ts.map +1 -0
  112. package/dist/tests/unit/commands/install.test.js +407 -0
  113. package/dist/tests/unit/commands/install.test.js.map +1 -0
  114. package/dist/vitest.config.d.ts.map +1 -1
  115. package/dist/vitest.config.js +9 -3
  116. package/dist/vitest.config.js.map +1 -1
  117. package/package.json +4 -3
@@ -0,0 +1,308 @@
1
+ /**
2
+ * Unit tests for recommend.helpers.ts pure logic functions
3
+ *
4
+ * Tests validateTrustTier, isNetworkError, buildStackFromAnalysis,
5
+ * formatAsJson, formatOfflineResults, formatRecommendations.
6
+ * No mocking required — all functions are pure.
7
+ */
8
+ import { describe, it, expect } from 'vitest';
9
+ import { validateTrustTier, isNetworkError, buildStackFromAnalysis, formatAsJson, formatOfflineResults, formatRecommendations, } from '../src/commands/recommend.helpers.js';
10
+ // ============================================================================
11
+ // Helpers
12
+ // ============================================================================
13
+ /** Minimal CodebaseContext with only the fields the helpers actually read */
14
+ function makeContext(overrides) {
15
+ return {
16
+ frameworks: [
17
+ { name: 'React', confidence: 0.95, evidence: [] },
18
+ { name: 'Vitest', confidence: 0.8, evidence: [] },
19
+ ],
20
+ dependencies: [
21
+ { name: 'react', isDev: false, version: '18.0.0' },
22
+ { name: 'vitest', isDev: true, version: '1.0.0' },
23
+ { name: 'express', isDev: false, version: '4.0.0' },
24
+ ],
25
+ stats: { totalFiles: 42, totalLines: 5000 },
26
+ ...overrides,
27
+ };
28
+ }
29
+ function makeResponse(overrides) {
30
+ return {
31
+ recommendations: [
32
+ {
33
+ skill_id: 'acme/linter',
34
+ name: 'linter',
35
+ reason: 'Improves code quality',
36
+ similarity_score: 0.85,
37
+ trust_tier: 'verified',
38
+ quality_score: 92,
39
+ roles: ['code-quality'],
40
+ },
41
+ ],
42
+ candidates_considered: 50,
43
+ overlap_filtered: 2,
44
+ role_filtered: 1,
45
+ context: {
46
+ installed_count: 3,
47
+ has_project_context: true,
48
+ using_semantic_matching: true,
49
+ auto_detected: true,
50
+ },
51
+ timing: { totalMs: 123 },
52
+ ...overrides,
53
+ };
54
+ }
55
+ // ============================================================================
56
+ // validateTrustTier
57
+ // ============================================================================
58
+ describe('validateTrustTier', () => {
59
+ it('accepts "verified"', () => {
60
+ expect(validateTrustTier('verified')).toBe('verified');
61
+ });
62
+ it('accepts "community"', () => {
63
+ expect(validateTrustTier('community')).toBe('community');
64
+ });
65
+ it('accepts "experimental"', () => {
66
+ expect(validateTrustTier('experimental')).toBe('experimental');
67
+ });
68
+ it('accepts "unknown"', () => {
69
+ expect(validateTrustTier('unknown')).toBe('unknown');
70
+ });
71
+ it('returns "unknown" for invalid string', () => {
72
+ expect(validateTrustTier('invalid')).toBe('unknown');
73
+ });
74
+ it('returns "unknown" for non-string input', () => {
75
+ expect(validateTrustTier(42)).toBe('unknown');
76
+ expect(validateTrustTier(null)).toBe('unknown');
77
+ expect(validateTrustTier(undefined)).toBe('unknown');
78
+ });
79
+ });
80
+ // ============================================================================
81
+ // isNetworkError
82
+ // ============================================================================
83
+ describe('isNetworkError', () => {
84
+ it('detects "fetch failed"', () => {
85
+ expect(isNetworkError(new Error('fetch failed'))).toBe(true);
86
+ });
87
+ it('detects "network" errors', () => {
88
+ expect(isNetworkError(new Error('Network error occurred'))).toBe(true);
89
+ });
90
+ it('detects ENOTFOUND', () => {
91
+ expect(isNetworkError(new Error('getaddrinfo ENOTFOUND api.example.com'))).toBe(true);
92
+ });
93
+ it('detects ECONNREFUSED', () => {
94
+ expect(isNetworkError(new Error('connect ECONNREFUSED 127.0.0.1:3000'))).toBe(true);
95
+ });
96
+ it('detects timeout', () => {
97
+ expect(isNetworkError(new Error('request timeout'))).toBe(true);
98
+ });
99
+ it('detects socket errors', () => {
100
+ expect(isNetworkError(new Error('socket hang up'))).toBe(true);
101
+ });
102
+ it('detects AbortError by name', () => {
103
+ const err = new Error('aborted');
104
+ err.name = 'AbortError';
105
+ expect(isNetworkError(err)).toBe(true);
106
+ });
107
+ it('returns false for non-network errors', () => {
108
+ expect(isNetworkError(new Error('syntax error'))).toBe(false);
109
+ });
110
+ it('returns false for non-Error values', () => {
111
+ expect(isNetworkError('string')).toBe(false);
112
+ expect(isNetworkError(42)).toBe(false);
113
+ expect(isNetworkError(null)).toBe(false);
114
+ });
115
+ });
116
+ // ============================================================================
117
+ // buildStackFromAnalysis
118
+ // ============================================================================
119
+ describe('buildStackFromAnalysis', () => {
120
+ it('builds stack from frameworks and prod dependencies', () => {
121
+ const ctx = makeContext();
122
+ const stack = buildStackFromAnalysis(ctx);
123
+ expect(stack).toContain('react');
124
+ expect(stack).toContain('vitest');
125
+ expect(stack).toContain('express');
126
+ });
127
+ it('excludes dev dependencies', () => {
128
+ const ctx = makeContext({
129
+ dependencies: [{ name: 'vitest', isDev: true, version: '1.0.0' }],
130
+ frameworks: [],
131
+ });
132
+ const stack = buildStackFromAnalysis(ctx);
133
+ expect(stack).not.toContain('vitest');
134
+ });
135
+ it('deduplicates entries', () => {
136
+ const ctx = makeContext({
137
+ frameworks: [{ name: 'React', confidence: 0.9, evidence: [] }],
138
+ dependencies: [{ name: 'react', isDev: false, version: '18.0.0' }],
139
+ });
140
+ const stack = buildStackFromAnalysis(ctx);
141
+ const reactCount = stack.filter((s) => s === 'react').length;
142
+ expect(reactCount).toBe(1);
143
+ });
144
+ it('caps output at 10 items', () => {
145
+ const deps = Array.from({ length: 20 }, (_, i) => ({
146
+ name: `dep-${i}`,
147
+ isDev: false,
148
+ version: '1.0.0',
149
+ }));
150
+ const ctx = makeContext({ dependencies: deps, frameworks: [] });
151
+ const stack = buildStackFromAnalysis(ctx);
152
+ expect(stack.length).toBeLessThanOrEqual(10);
153
+ });
154
+ it('returns empty array for empty context', () => {
155
+ const ctx = makeContext({ frameworks: [], dependencies: [] });
156
+ expect(buildStackFromAnalysis(ctx)).toEqual([]);
157
+ });
158
+ });
159
+ // ============================================================================
160
+ // formatAsJson
161
+ // ============================================================================
162
+ describe('formatAsJson', () => {
163
+ it('returns valid JSON', () => {
164
+ const output = formatAsJson(makeResponse(), makeContext());
165
+ expect(() => JSON.parse(output)).not.toThrow();
166
+ });
167
+ it('includes recommendations in output', () => {
168
+ const parsed = JSON.parse(formatAsJson(makeResponse(), makeContext()));
169
+ expect(parsed.recommendations).toHaveLength(1);
170
+ expect(parsed.recommendations[0].name).toBe('linter');
171
+ });
172
+ it('includes analysis when context provided', () => {
173
+ const parsed = JSON.parse(formatAsJson(makeResponse(), makeContext()));
174
+ expect(parsed.analysis).not.toBeNull();
175
+ expect(parsed.analysis.frameworks).toHaveLength(2);
176
+ expect(parsed.analysis.frameworks[0].confidence).toBe(95);
177
+ });
178
+ it('sets analysis to null when no context', () => {
179
+ const parsed = JSON.parse(formatAsJson(makeResponse(), null));
180
+ expect(parsed.analysis).toBeNull();
181
+ });
182
+ it('includes meta fields', () => {
183
+ const parsed = JSON.parse(formatAsJson(makeResponse(), null));
184
+ expect(parsed.meta.candidates_considered).toBe(50);
185
+ expect(parsed.meta.overlap_filtered).toBe(2);
186
+ expect(parsed.meta.role_filtered).toBe(1);
187
+ expect(parsed.meta.timing_ms).toBe(123);
188
+ });
189
+ it('separates prod and dev dependencies', () => {
190
+ const parsed = JSON.parse(formatAsJson(makeResponse(), makeContext()));
191
+ const vitest = parsed.analysis.dependencies.find((d) => d.name === 'vitest');
192
+ expect(vitest.is_dev).toBe(true);
193
+ });
194
+ });
195
+ // ============================================================================
196
+ // formatRecommendations
197
+ // ============================================================================
198
+ describe('formatRecommendations', () => {
199
+ it('includes recommendation count', () => {
200
+ const output = formatRecommendations(makeResponse(), makeContext());
201
+ expect(output).toContain('1');
202
+ expect(output).toContain('recommendation');
203
+ });
204
+ it('includes skill name', () => {
205
+ const output = formatRecommendations(makeResponse(), null);
206
+ expect(output).toContain('linter');
207
+ });
208
+ it('includes candidates considered', () => {
209
+ const output = formatRecommendations(makeResponse(), null);
210
+ expect(output).toContain('50');
211
+ });
212
+ it('shows detected frameworks from context', () => {
213
+ const output = formatRecommendations(makeResponse(), makeContext());
214
+ expect(output).toContain('React');
215
+ });
216
+ it('shows suggestions when no recommendations', () => {
217
+ const response = makeResponse({ recommendations: [] });
218
+ const output = formatRecommendations(response, null);
219
+ expect(output).toContain('No recommendations found');
220
+ expect(output).toContain('package.json');
221
+ });
222
+ it('shows role filter hint when active and no results', () => {
223
+ const response = makeResponse({
224
+ recommendations: [],
225
+ context: {
226
+ installed_count: 0,
227
+ has_project_context: true,
228
+ using_semantic_matching: true,
229
+ auto_detected: false,
230
+ role_filter: 'testing',
231
+ },
232
+ });
233
+ const output = formatRecommendations(response, null);
234
+ expect(output).toContain('--role');
235
+ expect(output).toContain('testing');
236
+ });
237
+ it('shows overlap filtered count', () => {
238
+ const output = formatRecommendations(makeResponse(), null);
239
+ expect(output).toContain('2');
240
+ });
241
+ it('shows timing', () => {
242
+ const output = formatRecommendations(makeResponse(), null);
243
+ expect(output).toContain('123ms');
244
+ });
245
+ it('displays N/A for negative similarity scores', () => {
246
+ const response = makeResponse({
247
+ recommendations: [
248
+ {
249
+ skill_id: 'a/b',
250
+ name: 'test',
251
+ reason: 'r',
252
+ similarity_score: -1,
253
+ trust_tier: 'community',
254
+ quality_score: 50,
255
+ },
256
+ ],
257
+ });
258
+ const output = formatRecommendations(response, null);
259
+ expect(output).toContain('N/A');
260
+ });
261
+ });
262
+ // ============================================================================
263
+ // formatOfflineResults
264
+ // ============================================================================
265
+ describe('formatOfflineResults', () => {
266
+ it('returns JSON when json flag is true', () => {
267
+ const output = formatOfflineResults(makeContext(), true);
268
+ const parsed = JSON.parse(output);
269
+ expect(parsed.offline).toBe(true);
270
+ expect(parsed.analysis.frameworks).toHaveLength(2);
271
+ expect(parsed.message).toContain('Unable to reach');
272
+ });
273
+ it('includes stats in JSON output', () => {
274
+ const parsed = JSON.parse(formatOfflineResults(makeContext(), true));
275
+ expect(parsed.analysis.stats.total_files).toBe(42);
276
+ expect(parsed.analysis.stats.total_lines).toBe(5000);
277
+ });
278
+ it('shows offline warning in text mode', () => {
279
+ const output = formatOfflineResults(makeContext(), false);
280
+ expect(output).toContain('Unable to reach Skillsmith API');
281
+ });
282
+ it('shows frameworks in text mode', () => {
283
+ const output = formatOfflineResults(makeContext(), false);
284
+ expect(output).toContain('React');
285
+ expect(output).toContain('95%');
286
+ });
287
+ it('shows prod dependencies in text mode', () => {
288
+ const output = formatOfflineResults(makeContext(), false);
289
+ expect(output).toContain('react');
290
+ expect(output).toContain('express');
291
+ });
292
+ it('shows file stats in text mode', () => {
293
+ const output = formatOfflineResults(makeContext(), false);
294
+ expect(output).toContain('42');
295
+ expect(output).toContain('5,000');
296
+ });
297
+ it('handles empty frameworks', () => {
298
+ const ctx = makeContext({ frameworks: [] });
299
+ const output = formatOfflineResults(ctx, false);
300
+ expect(output).not.toContain('Detected Frameworks');
301
+ });
302
+ it('handles empty dependencies', () => {
303
+ const ctx = makeContext({ dependencies: [] });
304
+ const output = formatOfflineResults(ctx, false);
305
+ expect(output).not.toContain('Key Dependencies');
306
+ });
307
+ });
308
+ //# sourceMappingURL=recommend-helpers.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recommend-helpers.test.js","sourceRoot":"","sources":["../../tests/recommend-helpers.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Unit tests for recommend-scoring.ts pure logic functions
3
+ *
4
+ * Tests inferRolesFromTags, normalizeSkillName, skillsOverlap, filterOverlappingSkills.
5
+ * No mocking required — all functions are pure.
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=recommend-scoring.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recommend-scoring.test.d.ts","sourceRoot":"","sources":["../../tests/recommend-scoring.test.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
@@ -0,0 +1,184 @@
1
+ /**
2
+ * Unit tests for recommend-scoring.ts pure logic functions
3
+ *
4
+ * Tests inferRolesFromTags, normalizeSkillName, skillsOverlap, filterOverlappingSkills.
5
+ * No mocking required — all functions are pure.
6
+ */
7
+ import { describe, it, expect } from 'vitest';
8
+ import { inferRolesFromTags, normalizeSkillName, skillsOverlap, filterOverlappingSkills, } from '../src/commands/recommend-scoring.js';
9
+ // ============================================================================
10
+ // inferRolesFromTags
11
+ // ============================================================================
12
+ describe('inferRolesFromTags', () => {
13
+ it('returns empty array for empty tags', () => {
14
+ expect(inferRolesFromTags([])).toEqual([]);
15
+ });
16
+ it('returns empty array for unrecognized tags', () => {
17
+ expect(inferRolesFromTags(['banana', 'spaceship'])).toEqual([]);
18
+ });
19
+ it('infers code-quality from lint-related tags', () => {
20
+ const roles = inferRolesFromTags(['lint']);
21
+ expect(roles).toContain('code-quality');
22
+ });
23
+ it('infers testing from test-related tags', () => {
24
+ const roles = inferRolesFromTags(['vitest']);
25
+ expect(roles).toContain('testing');
26
+ });
27
+ it('infers documentation from docs tags', () => {
28
+ const roles = inferRolesFromTags(['jsdoc']);
29
+ expect(roles).toContain('documentation');
30
+ });
31
+ it('infers workflow from CI/CD tags', () => {
32
+ const roles = inferRolesFromTags(['ci-cd']);
33
+ expect(roles).toContain('workflow');
34
+ });
35
+ it('infers security from security tags', () => {
36
+ const roles = inferRolesFromTags(['vulnerability']);
37
+ expect(roles).toContain('security');
38
+ });
39
+ it('infers development-partner from AI tags', () => {
40
+ const roles = inferRolesFromTags(['copilot']);
41
+ expect(roles).toContain('development-partner');
42
+ });
43
+ it('deduplicates roles from multiple matching tags', () => {
44
+ const roles = inferRolesFromTags(['lint', 'eslint', 'format']);
45
+ expect(roles).toEqual(['code-quality']);
46
+ });
47
+ it('returns multiple roles for diverse tags', () => {
48
+ const roles = inferRolesFromTags(['lint', 'testing', 'deploy']);
49
+ expect(roles).toContain('code-quality');
50
+ expect(roles).toContain('testing');
51
+ expect(roles).toContain('workflow');
52
+ expect(roles).toHaveLength(3);
53
+ });
54
+ it('normalizes hyphens and underscores in tags', () => {
55
+ const roles = inferRolesFromTags(['code_review']);
56
+ expect(roles).toContain('code-quality');
57
+ });
58
+ it('is case-insensitive', () => {
59
+ const roles = inferRolesFromTags(['LINT', 'Testing']);
60
+ expect(roles).toContain('code-quality');
61
+ expect(roles).toContain('testing');
62
+ });
63
+ });
64
+ // ============================================================================
65
+ // normalizeSkillName
66
+ // ============================================================================
67
+ describe('normalizeSkillName', () => {
68
+ it('lowercases the name', () => {
69
+ expect(normalizeSkillName('MyLinter')).toBe('mylinter');
70
+ });
71
+ it('removes hyphens and underscores', () => {
72
+ expect(normalizeSkillName('my-linter_tool')).toBe('mylintertool');
73
+ });
74
+ it('strips leading "skill" prefix', () => {
75
+ expect(normalizeSkillName('skill-formatter')).toBe('formatter');
76
+ });
77
+ it('strips trailing "skill" suffix', () => {
78
+ expect(normalizeSkillName('lint-skill')).toBe('lint');
79
+ });
80
+ it('strips leading "helper" prefix', () => {
81
+ expect(normalizeSkillName('helper-utils')).toBe('utils');
82
+ });
83
+ it('strips trailing "helper" suffix', () => {
84
+ expect(normalizeSkillName('code-helper')).toBe('code');
85
+ });
86
+ it('trims whitespace', () => {
87
+ expect(normalizeSkillName(' linter ')).toBe('linter');
88
+ });
89
+ it('handles combined normalization', () => {
90
+ expect(normalizeSkillName('Skill-Code_Helper')).toBe('code');
91
+ });
92
+ });
93
+ // ============================================================================
94
+ // skillsOverlap
95
+ // ============================================================================
96
+ describe('skillsOverlap', () => {
97
+ const makeInstalled = (name, tags = []) => ({
98
+ name,
99
+ directory: name,
100
+ tags,
101
+ category: null,
102
+ });
103
+ const makeRecommended = (name, skillId) => ({
104
+ skill_id: skillId,
105
+ name,
106
+ reason: 'test',
107
+ similarity_score: 0.8,
108
+ trust_tier: 'community',
109
+ quality_score: 80,
110
+ });
111
+ it('detects exact name match after normalization', () => {
112
+ const installed = makeInstalled('lint-skill');
113
+ const recommended = makeRecommended('skill-lint', 'author/skill-lint');
114
+ expect(skillsOverlap(installed, recommended)).toBe(true);
115
+ });
116
+ it('detects when skill_id contains installed name', () => {
117
+ const installed = makeInstalled('formatter');
118
+ const recommended = makeRecommended('code-formatter-pro', 'acme/formatter-pro');
119
+ expect(skillsOverlap(installed, recommended)).toBe(true);
120
+ });
121
+ it('detects substring overlap for names >= 4 chars', () => {
122
+ const installed = makeInstalled('linter');
123
+ const recommended = makeRecommended('super-linter', 'acme/super-linter');
124
+ expect(skillsOverlap(installed, recommended)).toBe(true);
125
+ });
126
+ it('does not detect substring overlap for short names', () => {
127
+ // Short names (<4 chars) skip substring check, but skill_id check still applies
128
+ // Use a skill_id that does NOT contain the installed name
129
+ const installed = makeInstalled('go');
130
+ const recommended = makeRecommended('rust-tools', 'acme/rust-tools');
131
+ expect(skillsOverlap(installed, recommended)).toBe(false);
132
+ });
133
+ it('detects tag overlap with recommended name parts', () => {
134
+ const installed = makeInstalled('my-tool', ['testing', 'vitest']);
135
+ const recommended = makeRecommended('vitest-helper', 'acme/vitest-helper');
136
+ expect(skillsOverlap(installed, recommended)).toBe(true);
137
+ });
138
+ it('returns false for unrelated skills', () => {
139
+ const installed = makeInstalled('formatter', ['formatting']);
140
+ const recommended = makeRecommended('security-auditor', 'acme/security-auditor');
141
+ expect(skillsOverlap(installed, recommended)).toBe(false);
142
+ });
143
+ });
144
+ // ============================================================================
145
+ // filterOverlappingSkills
146
+ // ============================================================================
147
+ describe('filterOverlappingSkills', () => {
148
+ const makeInstalled = (name, tags = []) => ({
149
+ name,
150
+ directory: name,
151
+ tags,
152
+ category: null,
153
+ });
154
+ const makeRecommended = (name, skillId) => ({
155
+ skill_id: skillId,
156
+ name,
157
+ reason: 'test',
158
+ similarity_score: 0.8,
159
+ trust_tier: 'community',
160
+ quality_score: 80,
161
+ });
162
+ it('returns all recommendations when no installed skills', () => {
163
+ const recs = [makeRecommended('foo', 'a/foo'), makeRecommended('bar', 'a/bar')];
164
+ const result = filterOverlappingSkills(recs, []);
165
+ expect(result.filtered).toHaveLength(2);
166
+ expect(result.overlapCount).toBe(0);
167
+ });
168
+ it('filters overlapping recommendations', () => {
169
+ const recs = [makeRecommended('linter', 'a/linter'), makeRecommended('security', 'a/security')];
170
+ const installed = [makeInstalled('linter')];
171
+ const result = filterOverlappingSkills(recs, installed);
172
+ expect(result.filtered).toHaveLength(1);
173
+ expect(result.filtered[0].name).toBe('security');
174
+ expect(result.overlapCount).toBe(1);
175
+ });
176
+ it('returns empty array when all overlap', () => {
177
+ const recs = [makeRecommended('linter', 'a/linter')];
178
+ const installed = [makeInstalled('linter')];
179
+ const result = filterOverlappingSkills(recs, installed);
180
+ expect(result.filtered).toHaveLength(0);
181
+ expect(result.overlapCount).toBe(1);
182
+ });
183
+ });
184
+ //# sourceMappingURL=recommend-scoring.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recommend-scoring.test.js","sourceRoot":"","sources":["../../tests/recommend-scoring.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Unit tests for tool-analyzer.ts pure logic functions
3
+ *
4
+ * Tests analyzeToolRequirements, formatToolList, parseToolsString, validateTools.
5
+ * No mocking required — all functions are pure.
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=tool-analyzer.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-analyzer.test.d.ts","sourceRoot":"","sources":["../../tests/tool-analyzer.test.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}