@skillsmith/cli 0.1.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 (110) hide show
  1. package/dist/.tsbuildinfo +1 -0
  2. package/dist/src/commands/author.d.ts +33 -0
  3. package/dist/src/commands/author.d.ts.map +1 -0
  4. package/dist/src/commands/author.js +337 -0
  5. package/dist/src/commands/author.js.map +1 -0
  6. package/dist/src/commands/index.d.ts +9 -0
  7. package/dist/src/commands/index.d.ts.map +1 -0
  8. package/dist/src/commands/index.js +12 -0
  9. package/dist/src/commands/index.js.map +1 -0
  10. package/dist/src/commands/manage.d.ts +37 -0
  11. package/dist/src/commands/manage.d.ts.map +1 -0
  12. package/dist/src/commands/manage.js +308 -0
  13. package/dist/src/commands/manage.js.map +1 -0
  14. package/dist/src/commands/search.d.ts +12 -0
  15. package/dist/src/commands/search.d.ts.map +1 -0
  16. package/dist/src/commands/search.js +316 -0
  17. package/dist/src/commands/search.js.map +1 -0
  18. package/dist/src/config.d.ts +19 -0
  19. package/dist/src/config.d.ts.map +1 -0
  20. package/dist/src/config.js +21 -0
  21. package/dist/src/config.js.map +1 -0
  22. package/dist/src/import.d.ts +29 -0
  23. package/dist/src/import.d.ts.map +1 -0
  24. package/dist/src/import.js +255 -0
  25. package/dist/src/import.js.map +1 -0
  26. package/dist/src/index.d.ts +16 -0
  27. package/dist/src/index.d.ts.map +1 -0
  28. package/dist/src/index.js +65 -0
  29. package/dist/src/index.js.map +1 -0
  30. package/dist/src/templates/index.d.ts +8 -0
  31. package/dist/src/templates/index.d.ts.map +1 -0
  32. package/dist/src/templates/index.js +8 -0
  33. package/dist/src/templates/index.js.map +1 -0
  34. package/dist/src/templates/readme.md.template.d.ts +8 -0
  35. package/dist/src/templates/readme.md.template.d.ts.map +1 -0
  36. package/dist/src/templates/readme.md.template.js +86 -0
  37. package/dist/src/templates/readme.md.template.js.map +1 -0
  38. package/dist/src/templates/skill.md.template.d.ts +8 -0
  39. package/dist/src/templates/skill.md.template.d.ts.map +1 -0
  40. package/dist/src/templates/skill.md.template.js +99 -0
  41. package/dist/src/templates/skill.md.template.js.map +1 -0
  42. package/dist/src/utils/license.d.ts +82 -0
  43. package/dist/src/utils/license.d.ts.map +1 -0
  44. package/dist/src/utils/license.js +282 -0
  45. package/dist/src/utils/license.js.map +1 -0
  46. package/dist/src/utils/license.test.d.ts +7 -0
  47. package/dist/src/utils/license.test.d.ts.map +1 -0
  48. package/dist/src/utils/license.test.js +303 -0
  49. package/dist/src/utils/license.test.js.map +1 -0
  50. package/dist/src/utils/sanitize.d.ts +30 -0
  51. package/dist/src/utils/sanitize.d.ts.map +1 -0
  52. package/dist/src/utils/sanitize.js +45 -0
  53. package/dist/src/utils/sanitize.js.map +1 -0
  54. package/dist/tests/author.test.d.ts +5 -0
  55. package/dist/tests/author.test.d.ts.map +1 -0
  56. package/dist/tests/author.test.js +149 -0
  57. package/dist/tests/author.test.js.map +1 -0
  58. package/dist/tests/e2e/author.e2e.test.d.ts +9 -0
  59. package/dist/tests/e2e/author.e2e.test.d.ts.map +1 -0
  60. package/dist/tests/e2e/author.e2e.test.js +346 -0
  61. package/dist/tests/e2e/author.e2e.test.js.map +1 -0
  62. package/dist/tests/e2e/import.e2e.test.d.ts +10 -0
  63. package/dist/tests/e2e/import.e2e.test.d.ts.map +1 -0
  64. package/dist/tests/e2e/import.e2e.test.js +213 -0
  65. package/dist/tests/e2e/import.e2e.test.js.map +1 -0
  66. package/dist/tests/e2e/manage.e2e.test.d.ts +9 -0
  67. package/dist/tests/e2e/manage.e2e.test.d.ts.map +1 -0
  68. package/dist/tests/e2e/manage.e2e.test.js +277 -0
  69. package/dist/tests/e2e/manage.e2e.test.js.map +1 -0
  70. package/dist/tests/e2e/search.e2e.test.d.ts +10 -0
  71. package/dist/tests/e2e/search.e2e.test.d.ts.map +1 -0
  72. package/dist/tests/e2e/search.e2e.test.js +267 -0
  73. package/dist/tests/e2e/search.e2e.test.js.map +1 -0
  74. package/dist/tests/e2e/test-config.d.ts +39 -0
  75. package/dist/tests/e2e/test-config.d.ts.map +1 -0
  76. package/dist/tests/e2e/test-config.js +44 -0
  77. package/dist/tests/e2e/test-config.js.map +1 -0
  78. package/dist/tests/e2e/utils/baseline-collector.d.ts +107 -0
  79. package/dist/tests/e2e/utils/baseline-collector.d.ts.map +1 -0
  80. package/dist/tests/e2e/utils/baseline-collector.js +211 -0
  81. package/dist/tests/e2e/utils/baseline-collector.js.map +1 -0
  82. package/dist/tests/e2e/utils/hardcoded-detector.d.ts +46 -0
  83. package/dist/tests/e2e/utils/hardcoded-detector.d.ts.map +1 -0
  84. package/dist/tests/e2e/utils/hardcoded-detector.js +197 -0
  85. package/dist/tests/e2e/utils/hardcoded-detector.js.map +1 -0
  86. package/dist/tests/e2e/utils/index.d.ts +8 -0
  87. package/dist/tests/e2e/utils/index.d.ts.map +1 -0
  88. package/dist/tests/e2e/utils/index.js +8 -0
  89. package/dist/tests/e2e/utils/index.js.map +1 -0
  90. package/dist/tests/e2e/utils/linear-reporter.d.ts +60 -0
  91. package/dist/tests/e2e/utils/linear-reporter.d.ts.map +1 -0
  92. package/dist/tests/e2e/utils/linear-reporter.js +223 -0
  93. package/dist/tests/e2e/utils/linear-reporter.js.map +1 -0
  94. package/dist/tests/import.test.d.ts +5 -0
  95. package/dist/tests/import.test.d.ts.map +1 -0
  96. package/dist/tests/import.test.js +11 -0
  97. package/dist/tests/import.test.js.map +1 -0
  98. package/dist/tests/manage.test.d.ts +5 -0
  99. package/dist/tests/manage.test.d.ts.map +1 -0
  100. package/dist/tests/manage.test.js +135 -0
  101. package/dist/tests/manage.test.js.map +1 -0
  102. package/dist/tests/search.test.d.ts +5 -0
  103. package/dist/tests/search.test.d.ts.map +1 -0
  104. package/dist/tests/search.test.js +91 -0
  105. package/dist/tests/search.test.js.map +1 -0
  106. package/dist/vitest.config.d.ts +3 -0
  107. package/dist/vitest.config.d.ts.map +1 -0
  108. package/dist/vitest.config.js +9 -0
  109. package/dist/vitest.config.js.map +1 -0
  110. package/package.json +62 -0
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Linear Issue Reporter for E2E Test Failures
3
+ *
4
+ * Automatically creates Linear issues when E2E tests detect problems.
5
+ * Issues include detailed evidence for specialist agents to resolve.
6
+ *
7
+ * @see docs/testing/e2e-testing-plan.md
8
+ */
9
+ import type { HardcodedIssue } from './hardcoded-detector.js';
10
+ export interface LinearIssuePayload {
11
+ title: string;
12
+ description: string;
13
+ teamId?: string;
14
+ projectId?: string;
15
+ labelIds?: string[];
16
+ priority?: number;
17
+ estimate?: number;
18
+ }
19
+ export interface LinearIssueResult {
20
+ success: boolean;
21
+ issueId?: string;
22
+ issueUrl?: string;
23
+ error?: string;
24
+ }
25
+ export interface TestFailure {
26
+ testName: string;
27
+ testFile: string;
28
+ command: string;
29
+ error: string;
30
+ stdout?: string;
31
+ stderr?: string;
32
+ hardcodedIssues?: HardcodedIssue[];
33
+ duration?: number;
34
+ timestamp: string;
35
+ }
36
+ /**
37
+ * Create Linear issue description from test failure
38
+ */
39
+ export declare function createIssueDescription(failure: TestFailure): string;
40
+ /**
41
+ * Create Linear issue title from test failure
42
+ */
43
+ export declare function createIssueTitle(failure: TestFailure): string;
44
+ /**
45
+ * Create Linear issue via API
46
+ */
47
+ export declare function createLinearIssue(failure: TestFailure): Promise<LinearIssueResult>;
48
+ export declare function queueIssue(failure: TestFailure): void;
49
+ export declare function getQueuedIssues(): TestFailure[];
50
+ export declare function flushIssueQueue(): Promise<LinearIssueResult[]>;
51
+ declare const _default: {
52
+ createIssueDescription: typeof createIssueDescription;
53
+ createIssueTitle: typeof createIssueTitle;
54
+ createLinearIssue: typeof createLinearIssue;
55
+ queueIssue: typeof queueIssue;
56
+ getQueuedIssues: typeof getQueuedIssues;
57
+ flushIssueQueue: typeof flushIssueQueue;
58
+ };
59
+ export default _default;
60
+ //# sourceMappingURL=linear-reporter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"linear-reporter.d.ts","sourceRoot":"","sources":["../../../../tests/e2e/utils/linear-reporter.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAE7D,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,eAAe,CAAC,EAAE,cAAc,EAAE,CAAA;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;CAClB;AAyBD;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CA0FnE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAM7D;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAkFxF;AAOD,wBAAgB,UAAU,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,CAErD;AAED,wBAAgB,eAAe,IAAI,WAAW,EAAE,CAE/C;AAED,wBAAsB,eAAe,IAAI,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAepE;;;;;;;;;AAED,wBAOC"}
@@ -0,0 +1,223 @@
1
+ /**
2
+ * Linear Issue Reporter for E2E Test Failures
3
+ *
4
+ * Automatically creates Linear issues when E2E tests detect problems.
5
+ * Issues include detailed evidence for specialist agents to resolve.
6
+ *
7
+ * @see docs/testing/e2e-testing-plan.md
8
+ */
9
+ /**
10
+ * Format hardcoded issue for Linear description
11
+ */
12
+ function formatHardcodedEvidence(issues) {
13
+ if (issues.length === 0)
14
+ return '';
15
+ const lines = [
16
+ '## Hardcoded Values Detected',
17
+ '',
18
+ '| Type | Pattern | Value | Source |',
19
+ '|------|---------|-------|--------|',
20
+ ];
21
+ for (const issue of issues) {
22
+ lines.push(`| ${issue.type} | ${issue.pattern} | \`${issue.value}\` | ${issue.location.source} |`);
23
+ }
24
+ lines.push('');
25
+ return lines.join('\n');
26
+ }
27
+ /**
28
+ * Create Linear issue description from test failure
29
+ */
30
+ export function createIssueDescription(failure) {
31
+ const sections = [];
32
+ // Problem definition
33
+ sections.push('## Problem Definition');
34
+ sections.push('');
35
+ sections.push(`E2E test **${failure.testName}** failed during automated testing.`);
36
+ sections.push('');
37
+ sections.push(`**Test File**: \`${failure.testFile}\``);
38
+ sections.push(`**Command**: \`${failure.command}\``);
39
+ sections.push(`**Timestamp**: ${failure.timestamp}`);
40
+ if (failure.duration) {
41
+ sections.push(`**Duration**: ${failure.duration}ms`);
42
+ }
43
+ sections.push('');
44
+ // Error details
45
+ sections.push('## Error Details');
46
+ sections.push('');
47
+ sections.push('```');
48
+ sections.push(failure.error);
49
+ sections.push('```');
50
+ sections.push('');
51
+ // Hardcoded issues if present
52
+ if (failure.hardcodedIssues && failure.hardcodedIssues.length > 0) {
53
+ sections.push(formatHardcodedEvidence(failure.hardcodedIssues));
54
+ }
55
+ // Output evidence (truncated)
56
+ if (failure.stdout || failure.stderr) {
57
+ sections.push('## Command Output');
58
+ sections.push('');
59
+ if (failure.stdout) {
60
+ const truncatedStdout = failure.stdout.length > 1000
61
+ ? failure.stdout.substring(0, 1000) + '\n... (truncated)'
62
+ : failure.stdout;
63
+ sections.push('<details>');
64
+ sections.push('<summary>stdout</summary>');
65
+ sections.push('');
66
+ sections.push('```');
67
+ sections.push(truncatedStdout);
68
+ sections.push('```');
69
+ sections.push('</details>');
70
+ sections.push('');
71
+ }
72
+ if (failure.stderr) {
73
+ const truncatedStderr = failure.stderr.length > 1000
74
+ ? failure.stderr.substring(0, 1000) + '\n... (truncated)'
75
+ : failure.stderr;
76
+ sections.push('<details>');
77
+ sections.push('<summary>stderr</summary>');
78
+ sections.push('');
79
+ sections.push('```');
80
+ sections.push(truncatedStderr);
81
+ sections.push('```');
82
+ sections.push('</details>');
83
+ sections.push('');
84
+ }
85
+ }
86
+ // Recommended actions
87
+ sections.push('## Recommended Actions');
88
+ sections.push('');
89
+ if (failure.hardcodedIssues && failure.hardcodedIssues.length > 0) {
90
+ sections.push('1. Review hardcoded values detected above');
91
+ sections.push('2. Replace with environment variables or user-configurable options');
92
+ sections.push('3. Use platform-agnostic path resolution (os.homedir(), path.join())');
93
+ sections.push('4. Re-run E2E tests in Codespace to verify fix');
94
+ }
95
+ else {
96
+ sections.push('1. Review error message and stack trace');
97
+ sections.push('2. Check test assumptions about environment');
98
+ sections.push('3. Verify command works in clean Codespace environment');
99
+ sections.push('4. Re-run E2E tests to verify fix');
100
+ }
101
+ sections.push('');
102
+ // Environment info
103
+ sections.push('## Test Environment');
104
+ sections.push('');
105
+ sections.push('- **Type**: GitHub Codespaces');
106
+ sections.push('- **Node Version**: 20.x');
107
+ sections.push('- **Test Repository**: 021-school-platform');
108
+ sections.push('');
109
+ return sections.join('\n');
110
+ }
111
+ /**
112
+ * Create Linear issue title from test failure
113
+ */
114
+ export function createIssueTitle(failure) {
115
+ if (failure.hardcodedIssues && failure.hardcodedIssues.length > 0) {
116
+ const types = [...new Set(failure.hardcodedIssues.map((i) => i.type))];
117
+ return `[E2E] Hardcoded ${types.join(', ')} in ${failure.command}`;
118
+ }
119
+ return `[E2E] ${failure.testName} failed`;
120
+ }
121
+ /**
122
+ * Create Linear issue via API
123
+ */
124
+ export async function createLinearIssue(failure) {
125
+ const apiKey = process.env['LINEAR_API_KEY'];
126
+ if (!apiKey) {
127
+ console.warn('LINEAR_API_KEY not set, skipping issue creation');
128
+ return {
129
+ success: false,
130
+ error: 'LINEAR_API_KEY environment variable not set',
131
+ };
132
+ }
133
+ const title = createIssueTitle(failure);
134
+ const description = createIssueDescription(failure);
135
+ // GraphQL mutation for creating issue
136
+ const mutation = `
137
+ mutation CreateIssue($input: IssueCreateInput!) {
138
+ issueCreate(input: $input) {
139
+ success
140
+ issue {
141
+ id
142
+ identifier
143
+ url
144
+ }
145
+ }
146
+ }
147
+ `;
148
+ const variables = {
149
+ input: {
150
+ title,
151
+ description,
152
+ // Labels: bug, e2e, hardcoded (if applicable)
153
+ labelIds: failure.hardcodedIssues?.length ? ['bug', 'e2e', 'hardcoded'] : ['bug', 'e2e'],
154
+ priority: failure.hardcodedIssues?.some((i) => i.severity === 'error') ? 1 : 2,
155
+ },
156
+ };
157
+ try {
158
+ const response = await fetch('https://api.linear.app/graphql', {
159
+ method: 'POST',
160
+ headers: {
161
+ 'Content-Type': 'application/json',
162
+ Authorization: apiKey,
163
+ },
164
+ body: JSON.stringify({ query: mutation, variables }),
165
+ });
166
+ if (!response.ok) {
167
+ throw new Error(`Linear API error: ${response.status} ${response.statusText}`);
168
+ }
169
+ const result = (await response.json());
170
+ if (result.errors) {
171
+ throw new Error(`GraphQL errors: ${JSON.stringify(result.errors)}`);
172
+ }
173
+ const issueData = result.data?.issueCreate;
174
+ if (issueData?.success) {
175
+ return {
176
+ success: true,
177
+ issueId: issueData.issue.identifier,
178
+ issueUrl: issueData.issue.url,
179
+ };
180
+ }
181
+ return {
182
+ success: false,
183
+ error: 'Issue creation returned unsuccessful',
184
+ };
185
+ }
186
+ catch (error) {
187
+ return {
188
+ success: false,
189
+ error: error instanceof Error ? error.message : String(error),
190
+ };
191
+ }
192
+ }
193
+ /**
194
+ * Queue issue for batch creation (used when rate-limited)
195
+ */
196
+ const issueQueue = [];
197
+ export function queueIssue(failure) {
198
+ issueQueue.push(failure);
199
+ }
200
+ export function getQueuedIssues() {
201
+ return [...issueQueue];
202
+ }
203
+ export async function flushIssueQueue() {
204
+ const results = [];
205
+ for (const failure of issueQueue) {
206
+ const result = await createLinearIssue(failure);
207
+ results.push(result);
208
+ // Rate limit: wait 500ms between requests
209
+ await new Promise((resolve) => setTimeout(resolve, 500));
210
+ }
211
+ // Clear queue
212
+ issueQueue.length = 0;
213
+ return results;
214
+ }
215
+ export default {
216
+ createIssueDescription,
217
+ createIssueTitle,
218
+ createLinearIssue,
219
+ queueIssue,
220
+ getQueuedIssues,
221
+ flushIssueQueue,
222
+ };
223
+ //# sourceMappingURL=linear-reporter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"linear-reporter.js","sourceRoot":"","sources":["../../../../tests/e2e/utils/linear-reporter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * SMI-580: Import Script Tests
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=import.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"import.test.d.ts","sourceRoot":"","sources":["../../tests/import.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * SMI-580: Import Script Tests
3
+ */
4
+ import { describe, it, expect } from 'vitest';
5
+ describe('Import Script', () => {
6
+ it('should be importable', async () => {
7
+ // Basic import test - actual functionality tested in integration
8
+ expect(true).toBe(true);
9
+ });
10
+ });
11
+ //# sourceMappingURL=import.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"import.test.js","sourceRoot":"","sources":["../../tests/import.test.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE7C,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;IAC7B,EAAE,CAAC,sBAAsB,EAAE,KAAK,IAAI,EAAE;QACpC,iEAAiE;QACjE,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACzB,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * SMI-745: Skill Management Commands Tests
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=manage.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manage.test.d.ts","sourceRoot":"","sources":["../../tests/manage.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,135 @@
1
+ /**
2
+ * SMI-745: Skill Management Commands Tests
3
+ */
4
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
5
+ import { Command } from 'commander';
6
+ import { join } from 'path';
7
+ import { homedir } from 'os';
8
+ // Mock file system
9
+ vi.mock('fs/promises', () => ({
10
+ readdir: vi.fn(),
11
+ readFile: vi.fn(),
12
+ rm: vi.fn(),
13
+ stat: vi.fn(),
14
+ }));
15
+ // Mock inquirer
16
+ vi.mock('@inquirer/prompts', () => ({
17
+ confirm: vi.fn(),
18
+ }));
19
+ // Mock ora
20
+ vi.mock('ora', () => ({
21
+ default: vi.fn(() => ({
22
+ start: vi.fn().mockReturnThis(),
23
+ stop: vi.fn().mockReturnThis(),
24
+ succeed: vi.fn().mockReturnThis(),
25
+ fail: vi.fn().mockReturnThis(),
26
+ text: '',
27
+ })),
28
+ }));
29
+ // Mock core
30
+ vi.mock('@skillsmith/core', () => ({
31
+ createDatabase: vi.fn(() => ({
32
+ close: vi.fn(),
33
+ })),
34
+ SkillRepository: vi.fn(() => ({
35
+ findAll: vi.fn(() => ({ items: [], total: 0, limit: 1000, offset: 0, hasMore: false })),
36
+ })),
37
+ SkillParser: vi.fn(() => ({
38
+ parse: vi.fn(),
39
+ inferTrustTier: vi.fn(() => 'unknown'),
40
+ })),
41
+ }));
42
+ describe('SMI-745: Skill Management Commands', () => {
43
+ const EXPECTED_SKILLS_DIR = join(homedir(), '.claude', 'skills');
44
+ beforeEach(() => {
45
+ vi.clearAllMocks();
46
+ });
47
+ afterEach(() => {
48
+ vi.restoreAllMocks();
49
+ });
50
+ describe('createListCommand', () => {
51
+ it('creates a command with correct name', async () => {
52
+ const { createListCommand } = await import('../src/commands/manage.js');
53
+ const cmd = createListCommand();
54
+ expect(cmd).toBeInstanceOf(Command);
55
+ expect(cmd.name()).toBe('list');
56
+ });
57
+ it('has ls alias', async () => {
58
+ const { createListCommand } = await import('../src/commands/manage.js');
59
+ const cmd = createListCommand();
60
+ expect(cmd.aliases()).toContain('ls');
61
+ });
62
+ });
63
+ describe('createUpdateCommand', () => {
64
+ it('creates a command with correct name', async () => {
65
+ const { createUpdateCommand } = await import('../src/commands/manage.js');
66
+ const cmd = createUpdateCommand();
67
+ expect(cmd).toBeInstanceOf(Command);
68
+ expect(cmd.name()).toBe('update');
69
+ });
70
+ it('has database path option', async () => {
71
+ const { createUpdateCommand } = await import('../src/commands/manage.js');
72
+ const cmd = createUpdateCommand();
73
+ const dbOpt = cmd.options.find((o) => o.short === '-d');
74
+ expect(dbOpt).toBeDefined();
75
+ });
76
+ it('has --all option for updating all skills', async () => {
77
+ const { createUpdateCommand } = await import('../src/commands/manage.js');
78
+ const cmd = createUpdateCommand();
79
+ const allOpt = cmd.options.find((o) => o.short === '-a');
80
+ expect(allOpt).toBeDefined();
81
+ expect(allOpt?.long).toBe('--all');
82
+ });
83
+ it('accepts optional skill name argument', async () => {
84
+ const { createUpdateCommand } = await import('../src/commands/manage.js');
85
+ const cmd = createUpdateCommand();
86
+ // Has one optional argument
87
+ expect(cmd.registeredArguments.length).toBeGreaterThanOrEqual(0);
88
+ });
89
+ });
90
+ describe('createRemoveCommand', () => {
91
+ it('creates a command with correct name', async () => {
92
+ const { createRemoveCommand } = await import('../src/commands/manage.js');
93
+ const cmd = createRemoveCommand();
94
+ expect(cmd).toBeInstanceOf(Command);
95
+ expect(cmd.name()).toBe('remove');
96
+ });
97
+ it('has rm and uninstall aliases', async () => {
98
+ const { createRemoveCommand } = await import('../src/commands/manage.js');
99
+ const cmd = createRemoveCommand();
100
+ expect(cmd.aliases()).toContain('rm');
101
+ expect(cmd.aliases()).toContain('uninstall');
102
+ });
103
+ it('has force option to skip confirmation', async () => {
104
+ const { createRemoveCommand } = await import('../src/commands/manage.js');
105
+ const cmd = createRemoveCommand();
106
+ const forceOpt = cmd.options.find((o) => o.short === '-f');
107
+ expect(forceOpt).toBeDefined();
108
+ expect(forceOpt?.long).toBe('--force');
109
+ });
110
+ it('requires skill name argument', async () => {
111
+ const { createRemoveCommand } = await import('../src/commands/manage.js');
112
+ const cmd = createRemoveCommand();
113
+ expect(cmd.registeredArguments.length).toBe(1);
114
+ expect(cmd.registeredArguments[0]?.required).toBe(true);
115
+ });
116
+ });
117
+ describe('Skills Directory', () => {
118
+ it('uses correct skills directory path', () => {
119
+ expect(EXPECTED_SKILLS_DIR).toBe(join(homedir(), '.claude', 'skills'));
120
+ });
121
+ });
122
+ describe('getInstalledSkills', () => {
123
+ it('is exported from module', async () => {
124
+ const module = await import('../src/commands/manage.js');
125
+ expect(typeof module.getInstalledSkills).toBe('function');
126
+ });
127
+ });
128
+ describe('displaySkillsTable', () => {
129
+ it('is exported from module', async () => {
130
+ const module = await import('../src/commands/manage.js');
131
+ expect(typeof module.displaySkillsTable).toBe('function');
132
+ });
133
+ });
134
+ });
135
+ //# sourceMappingURL=manage.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manage.test.js","sourceRoot":"","sources":["../../tests/manage.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * SMI-744: Interactive Search Command Tests
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=search.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.test.d.ts","sourceRoot":"","sources":["../../tests/search.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * SMI-744: Interactive Search Command Tests
3
+ */
4
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
5
+ import { Command } from 'commander';
6
+ import { DEFAULT_DB_PATH } from '../src/config.js';
7
+ // Mock dependencies before importing the module
8
+ vi.mock('@inquirer/prompts', () => ({
9
+ input: vi.fn(),
10
+ checkbox: vi.fn(),
11
+ number: vi.fn(),
12
+ select: vi.fn(),
13
+ }));
14
+ vi.mock('@skillsmith/core', () => ({
15
+ createDatabase: vi.fn(() => ({
16
+ close: vi.fn(),
17
+ })),
18
+ SearchService: vi.fn(() => ({
19
+ search: vi.fn(() => ({
20
+ items: [],
21
+ total: 0,
22
+ limit: 20,
23
+ offset: 0,
24
+ hasMore: false,
25
+ })),
26
+ })),
27
+ }));
28
+ describe('SMI-744: Search Command', () => {
29
+ beforeEach(() => {
30
+ vi.clearAllMocks();
31
+ });
32
+ afterEach(() => {
33
+ vi.restoreAllMocks();
34
+ });
35
+ describe('createSearchCommand', () => {
36
+ it('creates a command with correct name', async () => {
37
+ const { createSearchCommand } = await import('../src/commands/search.js');
38
+ const cmd = createSearchCommand();
39
+ expect(cmd).toBeInstanceOf(Command);
40
+ expect(cmd.name()).toBe('search');
41
+ });
42
+ it('has interactive option', async () => {
43
+ const { createSearchCommand } = await import('../src/commands/search.js');
44
+ const cmd = createSearchCommand();
45
+ const interactiveOpt = cmd.options.find((o) => o.short === '-i');
46
+ expect(interactiveOpt).toBeDefined();
47
+ expect(interactiveOpt?.long).toBe('--interactive');
48
+ });
49
+ it('has database path option with default', async () => {
50
+ const { createSearchCommand } = await import('../src/commands/search.js');
51
+ const cmd = createSearchCommand();
52
+ const dbOpt = cmd.options.find((o) => o.short === '-d');
53
+ expect(dbOpt).toBeDefined();
54
+ expect(dbOpt?.defaultValue).toBe(DEFAULT_DB_PATH);
55
+ });
56
+ it('has limit option', async () => {
57
+ const { createSearchCommand } = await import('../src/commands/search.js');
58
+ const cmd = createSearchCommand();
59
+ const limitOpt = cmd.options.find((o) => o.short === '-l');
60
+ expect(limitOpt).toBeDefined();
61
+ });
62
+ it('has trust tier filter option', async () => {
63
+ const { createSearchCommand } = await import('../src/commands/search.js');
64
+ const cmd = createSearchCommand();
65
+ const tierOpt = cmd.options.find((o) => o.short === '-t');
66
+ expect(tierOpt).toBeDefined();
67
+ });
68
+ it('has minimum score filter option', async () => {
69
+ const { createSearchCommand } = await import('../src/commands/search.js');
70
+ const cmd = createSearchCommand();
71
+ const scoreOpt = cmd.options.find((o) => o.short === '-s');
72
+ expect(scoreOpt).toBeDefined();
73
+ });
74
+ });
75
+ describe('Trust Tier Colors', () => {
76
+ it('defines colors for all trust tiers', async () => {
77
+ // The colors are defined in the module
78
+ const trustTiers = ['verified', 'community', 'experimental', 'unknown'];
79
+ // All tiers should have associated colors (implementation detail)
80
+ expect(trustTiers.length).toBe(4);
81
+ });
82
+ });
83
+ describe('Pagination', () => {
84
+ it('uses default page size of 10', async () => {
85
+ // PAGE_SIZE constant in the module
86
+ const expectedPageSize = 10;
87
+ expect(expectedPageSize).toBe(10);
88
+ });
89
+ });
90
+ });
91
+ //# sourceMappingURL=search.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.test.js","sourceRoot":"","sources":["../../tests/search.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ declare const _default: import("vite").UserConfig;
2
+ export default _default;
3
+ //# sourceMappingURL=vitest.config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vitest.config.d.ts","sourceRoot":"","sources":["../vitest.config.ts"],"names":[],"mappings":";AAEA,wBAME"}
@@ -0,0 +1,9 @@
1
+ import { defineConfig } from 'vitest/config';
2
+ export default defineConfig({
3
+ test: {
4
+ globals: true,
5
+ environment: 'node',
6
+ include: ['tests/**/*.test.ts'],
7
+ },
8
+ });
9
+ //# sourceMappingURL=vitest.config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vitest.config.js","sourceRoot":"","sources":["../vitest.config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAE5C,eAAe,YAAY,CAAC;IAC1B,IAAI,EAAE;QACJ,OAAO,EAAE,IAAI;QACb,WAAW,EAAE,MAAM;QACnB,OAAO,EAAE,CAAC,oBAAoB,CAAC;KAChC;CACF,CAAC,CAAA"}