@skillsmith/cli 0.6.4 → 0.7.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.
- package/CHANGELOG.md +10 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/src/commands/audit-sources.action.d.ts.map +1 -1
- package/dist/src/commands/audit-sources.action.js +26 -5
- package/dist/src/commands/audit-sources.action.js.map +1 -1
- package/dist/src/commands/diff.d.ts.map +1 -1
- package/dist/src/commands/diff.js +36 -15
- package/dist/src/commands/diff.js.map +1 -1
- package/dist/src/commands/diff.test.js +22 -0
- package/dist/src/commands/diff.test.js.map +1 -1
- package/dist/src/commands/index.d.ts +1 -0
- package/dist/src/commands/index.d.ts.map +1 -1
- package/dist/src/commands/index.js +2 -0
- package/dist/src/commands/index.js.map +1 -1
- package/dist/src/commands/inventory.action.d.ts +55 -0
- package/dist/src/commands/inventory.action.d.ts.map +1 -0
- package/dist/src/commands/inventory.action.js +179 -0
- package/dist/src/commands/inventory.action.js.map +1 -0
- package/dist/src/commands/inventory.action.test.d.ts +19 -0
- package/dist/src/commands/inventory.action.test.d.ts.map +1 -0
- package/dist/src/commands/inventory.action.test.js +371 -0
- package/dist/src/commands/inventory.action.test.js.map +1 -0
- package/dist/src/commands/inventory.d.ts +21 -0
- package/dist/src/commands/inventory.d.ts.map +1 -0
- package/dist/src/commands/inventory.js +42 -0
- package/dist/src/commands/inventory.js.map +1 -0
- package/dist/src/index.js +3 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/utils/skills-directory.d.ts +42 -0
- package/dist/src/utils/skills-directory.d.ts.map +1 -1
- package/dist/src/utils/skills-directory.js +76 -0
- package/dist/src/utils/skills-directory.js.map +1 -1
- package/dist/tests/e2e/audit-sources-affix.test.d.ts +11 -0
- package/dist/tests/e2e/audit-sources-affix.test.d.ts.map +1 -0
- package/dist/tests/e2e/audit-sources-affix.test.js +121 -0
- package/dist/tests/e2e/audit-sources-affix.test.js.map +1 -0
- package/dist/tests/e2e/audit-sources-roundtrip.test.js +32 -0
- package/dist/tests/e2e/audit-sources-roundtrip.test.js.map +1 -1
- package/dist/tests/skills-directory-per-harness.test.d.ts +2 -0
- package/dist/tests/skills-directory-per-harness.test.d.ts.map +1 -0
- package/dist/tests/skills-directory-per-harness.test.js +116 -0
- package/dist/tests/skills-directory-per-harness.test.js.map +1 -0
- package/package.json +3 -3
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Tests for `skillsmith inventory` subcommands.
|
|
3
|
+
* @module @skillsmith/cli/commands/inventory.action.test
|
|
4
|
+
* @see SMI-5392 Wave 3 — CLI inventory push/status/forget-device (umbrella SMI-5382)
|
|
5
|
+
*
|
|
6
|
+
* Covers:
|
|
7
|
+
* push: renders applied / consent-off / disabled-locally output correctly
|
|
8
|
+
* push: maps each of the 4 typed errors to console.error + process.exit(1)
|
|
9
|
+
* status: prints device ID, last-push, opt-out flag, and harness presence
|
|
10
|
+
* forget-device: calls core forgetDevice and prints confirmation with prior ID
|
|
11
|
+
*
|
|
12
|
+
* instanceof strategy:
|
|
13
|
+
* @skillsmith/core is mocked with inline class definitions for the four error
|
|
14
|
+
* types. Because vi.mock factories are hoisted, both the source module and the
|
|
15
|
+
* test file receive the SAME class reference — so `err instanceof InventoryAuthError`
|
|
16
|
+
* inside inventoryPushActionImpl matches the errors thrown in tests.
|
|
17
|
+
*/
|
|
18
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
// @skillsmith/core/telemetry — passthrough so withTelemetry has no side effects
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
vi.mock('@skillsmith/core/telemetry', () => ({
|
|
23
|
+
withTelemetry: (fn) => fn,
|
|
24
|
+
}));
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
// @skillsmith/core — mock functions; inline class definitions for error types
|
|
27
|
+
// so instanceof checks work (same reference in source + test).
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
vi.mock('@skillsmith/core', () => {
|
|
30
|
+
class InventoryAuthError extends Error {
|
|
31
|
+
constructor(msg = 'Not authenticated. Run `skillsmith login` and try again.') {
|
|
32
|
+
super(msg);
|
|
33
|
+
this.name = 'InventoryAuthError';
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
class InventoryConflictError extends Error {
|
|
37
|
+
constructor(msg = 'device_conflict') {
|
|
38
|
+
super(msg);
|
|
39
|
+
this.name = 'InventoryConflictError';
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
class InventoryValidationError extends Error {
|
|
43
|
+
constructor(msg = 'invalid payload') {
|
|
44
|
+
super(msg);
|
|
45
|
+
this.name = 'InventoryValidationError';
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
class InventoryUploadError extends Error {
|
|
49
|
+
constructor(msg) {
|
|
50
|
+
super(msg);
|
|
51
|
+
this.name = 'InventoryUploadError';
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
pushInventory: vi.fn(),
|
|
56
|
+
getDeviceId: vi.fn(),
|
|
57
|
+
forgetDevice: vi.fn(),
|
|
58
|
+
getLastInventoryPushAt: vi.fn(),
|
|
59
|
+
isInventorySyncDisabledLocally: vi.fn(),
|
|
60
|
+
InventoryAuthError,
|
|
61
|
+
InventoryConflictError,
|
|
62
|
+
InventoryValidationError,
|
|
63
|
+
InventoryUploadError,
|
|
64
|
+
};
|
|
65
|
+
});
|
|
66
|
+
// ---------------------------------------------------------------------------
|
|
67
|
+
// @skillsmith/core/install — sync function, mock to return a fixed presence set
|
|
68
|
+
// ---------------------------------------------------------------------------
|
|
69
|
+
vi.mock('@skillsmith/core/install', () => ({
|
|
70
|
+
enumerateHarnessPresence: vi.fn(() => [
|
|
71
|
+
{ harness: 'claude-code', present: true, path: '/mock/.claude/skills' },
|
|
72
|
+
{ harness: 'cursor', present: false, path: '/mock/.cursor/skills' },
|
|
73
|
+
]),
|
|
74
|
+
}));
|
|
75
|
+
// ---------------------------------------------------------------------------
|
|
76
|
+
// CLI utilities
|
|
77
|
+
// ---------------------------------------------------------------------------
|
|
78
|
+
vi.mock('../utils/skills-directory.js', () => ({
|
|
79
|
+
getInstalledSkillsPerHarness: vi.fn(() => Promise.resolve([])),
|
|
80
|
+
}));
|
|
81
|
+
vi.mock('../version.js', () => ({ VERSION: '0.0.0-test' }));
|
|
82
|
+
// ---------------------------------------------------------------------------
|
|
83
|
+
// Import after mocks are registered
|
|
84
|
+
// ---------------------------------------------------------------------------
|
|
85
|
+
import { runPush, runStatus, runForgetDevice, inventoryPushActionImpl, inventoryStatusActionImpl, inventoryForgetDeviceActionImpl, } from './inventory.action.js';
|
|
86
|
+
import { pushInventory, getDeviceId, forgetDevice, getLastInventoryPushAt, isInventorySyncDisabledLocally, InventoryAuthError, InventoryConflictError, InventoryValidationError, InventoryUploadError, } from '@skillsmith/core';
|
|
87
|
+
import { enumerateHarnessPresence } from '@skillsmith/core/install';
|
|
88
|
+
import { getInstalledSkillsPerHarness } from '../utils/skills-directory.js';
|
|
89
|
+
const pushInventoryMock = vi.mocked(pushInventory);
|
|
90
|
+
const getDeviceIdMock = vi.mocked(getDeviceId);
|
|
91
|
+
const forgetDeviceMock = vi.mocked(forgetDevice);
|
|
92
|
+
const getLastInventoryPushAtMock = vi.mocked(getLastInventoryPushAt);
|
|
93
|
+
const isInventorySyncDisabledLocallyMock = vi.mocked(isInventorySyncDisabledLocally);
|
|
94
|
+
const enumerateHarnessPresenceMock = vi.mocked(enumerateHarnessPresence);
|
|
95
|
+
const getInstalledSkillsPerHarnessMock = vi.mocked(getInstalledSkillsPerHarness);
|
|
96
|
+
// ---------------------------------------------------------------------------
|
|
97
|
+
// Console capture helper
|
|
98
|
+
// ---------------------------------------------------------------------------
|
|
99
|
+
function captureConsole() {
|
|
100
|
+
const log = [];
|
|
101
|
+
const err = [];
|
|
102
|
+
vi.spyOn(console, 'log').mockImplementation((...args) => log.push(args.join(' ')));
|
|
103
|
+
vi.spyOn(console, 'error').mockImplementation((...args) => err.push(args.join(' ')));
|
|
104
|
+
return {
|
|
105
|
+
log,
|
|
106
|
+
err,
|
|
107
|
+
all: () => [...log, ...err],
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
// ---------------------------------------------------------------------------
|
|
111
|
+
// Setup / teardown
|
|
112
|
+
// ---------------------------------------------------------------------------
|
|
113
|
+
beforeEach(() => {
|
|
114
|
+
vi.clearAllMocks();
|
|
115
|
+
// Defaults so tests that don't care about these still get sensible values.
|
|
116
|
+
getDeviceIdMock.mockReturnValue('test-device-uuid-1234');
|
|
117
|
+
getLastInventoryPushAtMock.mockReturnValue(undefined);
|
|
118
|
+
isInventorySyncDisabledLocallyMock.mockReturnValue(false);
|
|
119
|
+
getInstalledSkillsPerHarnessMock.mockResolvedValue([]);
|
|
120
|
+
});
|
|
121
|
+
afterEach(() => {
|
|
122
|
+
vi.restoreAllMocks();
|
|
123
|
+
});
|
|
124
|
+
// ---------------------------------------------------------------------------
|
|
125
|
+
// push — happy-path rendering
|
|
126
|
+
// ---------------------------------------------------------------------------
|
|
127
|
+
describe('inventory push — happy paths', () => {
|
|
128
|
+
it('prints dim note when sync is locally disabled (disabled_locally)', async () => {
|
|
129
|
+
pushInventoryMock.mockResolvedValue({
|
|
130
|
+
ok: true,
|
|
131
|
+
applied: false,
|
|
132
|
+
reason: 'disabled_locally',
|
|
133
|
+
});
|
|
134
|
+
const cap = captureConsole();
|
|
135
|
+
await runPush();
|
|
136
|
+
const output = cap.all().join('\n');
|
|
137
|
+
expect(output).toContain('SKILLSMITH_INVENTORY_DISABLE');
|
|
138
|
+
expect(output).toContain('nothing sent');
|
|
139
|
+
});
|
|
140
|
+
it('prints yellow consent-off message when server returns consent_disabled', async () => {
|
|
141
|
+
pushInventoryMock.mockResolvedValue({
|
|
142
|
+
ok: true,
|
|
143
|
+
applied: false,
|
|
144
|
+
reason: 'consent_disabled',
|
|
145
|
+
});
|
|
146
|
+
const cap = captureConsole();
|
|
147
|
+
await runPush();
|
|
148
|
+
const output = cap.all().join('\n');
|
|
149
|
+
expect(output).toContain('sync is OFF');
|
|
150
|
+
expect(output).toContain('nothing stored');
|
|
151
|
+
});
|
|
152
|
+
it('prints green success line with device_id and counts when applied=true', async () => {
|
|
153
|
+
pushInventoryMock.mockResolvedValue({
|
|
154
|
+
ok: true,
|
|
155
|
+
applied: true,
|
|
156
|
+
device_id: 'abc-device-123',
|
|
157
|
+
skills_present: 7,
|
|
158
|
+
skills_absent: 2,
|
|
159
|
+
});
|
|
160
|
+
const cap = captureConsole();
|
|
161
|
+
await runPush();
|
|
162
|
+
const output = cap.all().join('\n');
|
|
163
|
+
expect(output).toContain('abc-device-123');
|
|
164
|
+
expect(output).toContain('7 present');
|
|
165
|
+
expect(output).toContain('2 marked absent');
|
|
166
|
+
});
|
|
167
|
+
it('prints defensive raw result for unexpected ok/reason combo', async () => {
|
|
168
|
+
pushInventoryMock.mockResolvedValue({ ok: false, applied: false, reason: 'unknown_reason' });
|
|
169
|
+
const cap = captureConsole();
|
|
170
|
+
await runPush();
|
|
171
|
+
const output = cap.all().join('\n');
|
|
172
|
+
expect(output).toContain('unknown_reason');
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
// ---------------------------------------------------------------------------
|
|
176
|
+
// push — typed error mapping → process.exit(1)
|
|
177
|
+
// ---------------------------------------------------------------------------
|
|
178
|
+
describe('inventory push — typed error mapping', () => {
|
|
179
|
+
function mockExit() {
|
|
180
|
+
return vi.spyOn(process, 'exit').mockImplementation((code) => {
|
|
181
|
+
throw new Error(`process.exit(${String(code)})`);
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
it('maps InventoryAuthError → "Not logged in" message + exit(1)', async () => {
|
|
185
|
+
const exitSpy = mockExit();
|
|
186
|
+
pushInventoryMock.mockRejectedValue(new InventoryAuthError());
|
|
187
|
+
const cap = captureConsole();
|
|
188
|
+
await expect(inventoryPushActionImpl()).rejects.toThrow('process.exit(1)');
|
|
189
|
+
expect(exitSpy).toHaveBeenCalledWith(1);
|
|
190
|
+
expect(cap.err.join(' ')).toContain('Not logged in');
|
|
191
|
+
});
|
|
192
|
+
it('maps InventoryConflictError → "forget-device" hint + exit(1)', async () => {
|
|
193
|
+
const exitSpy = mockExit();
|
|
194
|
+
pushInventoryMock.mockRejectedValue(new InventoryConflictError());
|
|
195
|
+
const cap = captureConsole();
|
|
196
|
+
await expect(inventoryPushActionImpl()).rejects.toThrow('process.exit(1)');
|
|
197
|
+
expect(exitSpy).toHaveBeenCalledWith(1);
|
|
198
|
+
expect(cap.err.join(' ')).toContain('forget-device');
|
|
199
|
+
});
|
|
200
|
+
it('maps InventoryValidationError → server message + exit(1)', async () => {
|
|
201
|
+
const exitSpy = mockExit();
|
|
202
|
+
pushInventoryMock.mockRejectedValue(new InventoryValidationError('skill_id_too_long'));
|
|
203
|
+
const cap = captureConsole();
|
|
204
|
+
await expect(inventoryPushActionImpl()).rejects.toThrow('process.exit(1)');
|
|
205
|
+
expect(exitSpy).toHaveBeenCalledWith(1);
|
|
206
|
+
expect(cap.err.join(' ')).toContain('skill_id_too_long');
|
|
207
|
+
});
|
|
208
|
+
it('maps InventoryUploadError → "Inventory upload failed." prefix + exit(1)', async () => {
|
|
209
|
+
const exitSpy = mockExit();
|
|
210
|
+
pushInventoryMock.mockRejectedValue(new InventoryUploadError('HTTP 503'));
|
|
211
|
+
const cap = captureConsole();
|
|
212
|
+
await expect(inventoryPushActionImpl()).rejects.toThrow('process.exit(1)');
|
|
213
|
+
expect(exitSpy).toHaveBeenCalledWith(1);
|
|
214
|
+
expect(cap.err.join(' ')).toContain('Inventory upload failed.');
|
|
215
|
+
expect(cap.err.join(' ')).toContain('HTTP 503');
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
// ---------------------------------------------------------------------------
|
|
219
|
+
// status — read-only local view
|
|
220
|
+
// ---------------------------------------------------------------------------
|
|
221
|
+
describe('inventory status', () => {
|
|
222
|
+
it('shows device ID when registered', async () => {
|
|
223
|
+
getDeviceIdMock.mockReturnValue('my-stable-device-uuid');
|
|
224
|
+
const cap = captureConsole();
|
|
225
|
+
await runStatus();
|
|
226
|
+
expect(cap.log.join('\n')).toContain('my-stable-device-uuid');
|
|
227
|
+
});
|
|
228
|
+
it('shows placeholder when device not yet registered', async () => {
|
|
229
|
+
getDeviceIdMock.mockReturnValue(undefined);
|
|
230
|
+
const cap = captureConsole();
|
|
231
|
+
await runStatus();
|
|
232
|
+
expect(cap.log.join('\n')).toContain('not yet registered');
|
|
233
|
+
});
|
|
234
|
+
it('shows "never" when no push has occurred', async () => {
|
|
235
|
+
getLastInventoryPushAtMock.mockReturnValue(undefined);
|
|
236
|
+
const cap = captureConsole();
|
|
237
|
+
await runStatus();
|
|
238
|
+
expect(cap.log.join('\n')).toContain('never');
|
|
239
|
+
});
|
|
240
|
+
it('shows last push timestamp when present', async () => {
|
|
241
|
+
getLastInventoryPushAtMock.mockReturnValue('2026-01-15T10:00:00.000Z');
|
|
242
|
+
const cap = captureConsole();
|
|
243
|
+
await runStatus();
|
|
244
|
+
expect(cap.log.join('\n')).toContain('2026-01-15T10:00:00.000Z');
|
|
245
|
+
});
|
|
246
|
+
it('shows opt-out warning when SKILLSMITH_INVENTORY_DISABLE is set', async () => {
|
|
247
|
+
isInventorySyncDisabledLocallyMock.mockReturnValue(true);
|
|
248
|
+
const cap = captureConsole();
|
|
249
|
+
await runStatus();
|
|
250
|
+
expect(cap.log.join('\n')).toContain('SKILLSMITH_INVENTORY_DISABLE');
|
|
251
|
+
});
|
|
252
|
+
it('lists harness presence from enumerateHarnessPresence', async () => {
|
|
253
|
+
enumerateHarnessPresenceMock.mockReturnValue([
|
|
254
|
+
{ harness: 'claude-code', present: true, path: '/mock/.claude/skills' },
|
|
255
|
+
{ harness: 'cursor', present: false, path: '/mock/.cursor/skills' },
|
|
256
|
+
]);
|
|
257
|
+
const cap = captureConsole();
|
|
258
|
+
await runStatus();
|
|
259
|
+
const out = cap.log.join('\n');
|
|
260
|
+
expect(out).toContain('claude-code');
|
|
261
|
+
expect(out).toContain('cursor');
|
|
262
|
+
});
|
|
263
|
+
it('shows skill count for present harnesses', async () => {
|
|
264
|
+
enumerateHarnessPresenceMock.mockReturnValue([
|
|
265
|
+
{ harness: 'claude-code', present: true, path: '/mock/.claude/skills' },
|
|
266
|
+
]);
|
|
267
|
+
getInstalledSkillsPerHarnessMock.mockResolvedValue([
|
|
268
|
+
{
|
|
269
|
+
harness: 'claude-code',
|
|
270
|
+
skillId: 'foo/bar',
|
|
271
|
+
version: '1.0.0',
|
|
272
|
+
contentHash: null,
|
|
273
|
+
path: '/mock/foo-bar',
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
harness: 'claude-code',
|
|
277
|
+
skillId: 'baz/qux',
|
|
278
|
+
version: null,
|
|
279
|
+
contentHash: null,
|
|
280
|
+
path: '/mock/baz-qux',
|
|
281
|
+
},
|
|
282
|
+
]);
|
|
283
|
+
const cap = captureConsole();
|
|
284
|
+
await runStatus();
|
|
285
|
+
expect(cap.log.join('\n')).toContain('2 skills');
|
|
286
|
+
});
|
|
287
|
+
it('lists skill IDs under each harness when --verbose is passed', async () => {
|
|
288
|
+
enumerateHarnessPresenceMock.mockReturnValue([
|
|
289
|
+
{ harness: 'claude-code', present: true, path: '/mock/.claude/skills' },
|
|
290
|
+
]);
|
|
291
|
+
getInstalledSkillsPerHarnessMock.mockResolvedValue([
|
|
292
|
+
{
|
|
293
|
+
harness: 'claude-code',
|
|
294
|
+
skillId: 'author/my-skill',
|
|
295
|
+
version: '1.0.0',
|
|
296
|
+
contentHash: null,
|
|
297
|
+
path: '/mock/my-skill',
|
|
298
|
+
},
|
|
299
|
+
]);
|
|
300
|
+
const cap = captureConsole();
|
|
301
|
+
await runStatus({ verbose: true });
|
|
302
|
+
expect(cap.log.join('\n')).toContain('author/my-skill');
|
|
303
|
+
});
|
|
304
|
+
it('does not list skill IDs when --verbose is not passed', async () => {
|
|
305
|
+
enumerateHarnessPresenceMock.mockReturnValue([
|
|
306
|
+
{ harness: 'claude-code', present: true, path: '/mock/.claude/skills' },
|
|
307
|
+
]);
|
|
308
|
+
getInstalledSkillsPerHarnessMock.mockResolvedValue([
|
|
309
|
+
{
|
|
310
|
+
harness: 'claude-code',
|
|
311
|
+
skillId: 'author/hidden-skill',
|
|
312
|
+
version: null,
|
|
313
|
+
contentHash: null,
|
|
314
|
+
path: '/mock/hidden',
|
|
315
|
+
},
|
|
316
|
+
]);
|
|
317
|
+
const cap = captureConsole();
|
|
318
|
+
await runStatus({ verbose: false });
|
|
319
|
+
expect(cap.log.join('\n')).not.toContain('author/hidden-skill');
|
|
320
|
+
});
|
|
321
|
+
it('passes through errors from getInstalledSkillsPerHarness to inventoryStatusActionImpl', async () => {
|
|
322
|
+
getInstalledSkillsPerHarnessMock.mockRejectedValue(new Error('disk error'));
|
|
323
|
+
const exitSpy = vi.spyOn(process, 'exit').mockImplementation((code) => {
|
|
324
|
+
throw new Error(`process.exit(${String(code)})`);
|
|
325
|
+
});
|
|
326
|
+
captureConsole();
|
|
327
|
+
await expect(inventoryStatusActionImpl({})).rejects.toThrow('process.exit(1)');
|
|
328
|
+
expect(exitSpy).toHaveBeenCalledWith(1);
|
|
329
|
+
});
|
|
330
|
+
});
|
|
331
|
+
// ---------------------------------------------------------------------------
|
|
332
|
+
// forget-device
|
|
333
|
+
// ---------------------------------------------------------------------------
|
|
334
|
+
describe('inventory forget-device', () => {
|
|
335
|
+
it('calls core forgetDevice', async () => {
|
|
336
|
+
getDeviceIdMock.mockReturnValue('old-device-uuid');
|
|
337
|
+
captureConsole();
|
|
338
|
+
await runForgetDevice();
|
|
339
|
+
expect(forgetDeviceMock).toHaveBeenCalledTimes(1);
|
|
340
|
+
});
|
|
341
|
+
it('confirms the previous device ID in output', async () => {
|
|
342
|
+
getDeviceIdMock.mockReturnValue('previous-device-abc');
|
|
343
|
+
const cap = captureConsole();
|
|
344
|
+
await runForgetDevice();
|
|
345
|
+
expect(cap.log.join('\n')).toContain('previous-device-abc');
|
|
346
|
+
});
|
|
347
|
+
it('shows "(none)" when there was no device ID to forget', async () => {
|
|
348
|
+
getDeviceIdMock.mockReturnValue(undefined);
|
|
349
|
+
const cap = captureConsole();
|
|
350
|
+
await runForgetDevice();
|
|
351
|
+
expect(cap.log.join('\n')).toContain('(none)');
|
|
352
|
+
});
|
|
353
|
+
it('mentions fresh device on next push', async () => {
|
|
354
|
+
getDeviceIdMock.mockReturnValue('any-device');
|
|
355
|
+
const cap = captureConsole();
|
|
356
|
+
await runForgetDevice();
|
|
357
|
+
expect(cap.log.join('\n')).toContain('fresh device');
|
|
358
|
+
});
|
|
359
|
+
it('passes through errors to inventoryForgetDeviceActionImpl + exit(1)', async () => {
|
|
360
|
+
forgetDeviceMock.mockImplementation(() => {
|
|
361
|
+
throw new Error('config write error');
|
|
362
|
+
});
|
|
363
|
+
const exitSpy = vi.spyOn(process, 'exit').mockImplementation((code) => {
|
|
364
|
+
throw new Error(`process.exit(${String(code)})`);
|
|
365
|
+
});
|
|
366
|
+
captureConsole();
|
|
367
|
+
await expect(inventoryForgetDeviceActionImpl()).rejects.toThrow('process.exit(1)');
|
|
368
|
+
expect(exitSpy).toHaveBeenCalledWith(1);
|
|
369
|
+
});
|
|
370
|
+
});
|
|
371
|
+
//# sourceMappingURL=inventory.action.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inventory.action.test.js","sourceRoot":"","sources":["../../../src/commands/inventory.action.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview `skillsmith inventory` command group — cross-harness inventory management.
|
|
3
|
+
* @module @skillsmith/cli/commands/inventory
|
|
4
|
+
* @see SMI-5392 Wave 3 — CLI `inventory` subcommands (umbrella SMI-5382).
|
|
5
|
+
* @see SMI-5128 sibling-split convention — action impls + withTelemetry wrappers
|
|
6
|
+
* live in inventory.action.ts; this file retains only the commander factory.
|
|
7
|
+
*
|
|
8
|
+
* Subcommands:
|
|
9
|
+
* skillsmith inventory push
|
|
10
|
+
* skillsmith inventory status [--verbose]
|
|
11
|
+
* skillsmith inventory forget-device
|
|
12
|
+
*/
|
|
13
|
+
import { Command } from 'commander';
|
|
14
|
+
/**
|
|
15
|
+
* Build and return the `inventory` commander group with its three subcommands.
|
|
16
|
+
*
|
|
17
|
+
* @see SMI-5392
|
|
18
|
+
*/
|
|
19
|
+
export declare function createInventoryCommand(): Command;
|
|
20
|
+
export { runPush, runStatus, runForgetDevice, inventoryPushActionImpl, inventoryStatusActionImpl, inventoryForgetDeviceActionImpl, } from './inventory.action.js';
|
|
21
|
+
//# sourceMappingURL=inventory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inventory.d.ts","sourceRoot":"","sources":["../../../src/commands/inventory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAYnC;;;;GAIG;AACH,wBAAgB,sBAAsB,IAAI,OAAO,CAsBhD;AAGD,OAAO,EACL,OAAO,EACP,SAAS,EACT,eAAe,EACf,uBAAuB,EACvB,yBAAyB,EACzB,+BAA+B,GAChC,MAAM,uBAAuB,CAAA"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview `skillsmith inventory` command group — cross-harness inventory management.
|
|
3
|
+
* @module @skillsmith/cli/commands/inventory
|
|
4
|
+
* @see SMI-5392 Wave 3 — CLI `inventory` subcommands (umbrella SMI-5382).
|
|
5
|
+
* @see SMI-5128 sibling-split convention — action impls + withTelemetry wrappers
|
|
6
|
+
* live in inventory.action.ts; this file retains only the commander factory.
|
|
7
|
+
*
|
|
8
|
+
* Subcommands:
|
|
9
|
+
* skillsmith inventory push
|
|
10
|
+
* skillsmith inventory status [--verbose]
|
|
11
|
+
* skillsmith inventory forget-device
|
|
12
|
+
*/
|
|
13
|
+
import { Command } from 'commander';
|
|
14
|
+
import { inventoryPushAction, inventoryStatusAction, inventoryForgetDeviceAction, } from './inventory.action.js';
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
// Command factory
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
/**
|
|
19
|
+
* Build and return the `inventory` commander group with its three subcommands.
|
|
20
|
+
*
|
|
21
|
+
* @see SMI-5392
|
|
22
|
+
*/
|
|
23
|
+
export function createInventoryCommand() {
|
|
24
|
+
const inventory = new Command('inventory').description('Manage cross-harness skill inventory sync and device registration');
|
|
25
|
+
inventory
|
|
26
|
+
.command('push')
|
|
27
|
+
.description("Push this device's skill inventory snapshot to the registry")
|
|
28
|
+
.action(inventoryPushAction);
|
|
29
|
+
inventory
|
|
30
|
+
.command('status')
|
|
31
|
+
.description('Show local inventory state (read-only, no network calls)')
|
|
32
|
+
.option('--verbose', 'List individual skill IDs under each harness')
|
|
33
|
+
.action(inventoryStatusAction);
|
|
34
|
+
inventory
|
|
35
|
+
.command('forget-device')
|
|
36
|
+
.description('Clear the local device registration; the next push will create a fresh device')
|
|
37
|
+
.action(inventoryForgetDeviceAction);
|
|
38
|
+
return inventory;
|
|
39
|
+
}
|
|
40
|
+
// Internal exports for tests — sourced from inventory.action.ts (SMI-5128 split).
|
|
41
|
+
export { runPush, runStatus, runForgetDevice, inventoryPushActionImpl, inventoryStatusActionImpl, inventoryForgetDeviceActionImpl, } from './inventory.action.js';
|
|
42
|
+
//# sourceMappingURL=inventory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inventory.js","sourceRoot":"","sources":["../../../src/commands/inventory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAEnC,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,2BAA2B,GAC5B,MAAM,uBAAuB,CAAA;AAE9B,8EAA8E;AAC9E,kBAAkB;AAClB,8EAA8E;AAE9E;;;;GAIG;AACH,MAAM,UAAU,sBAAsB;IACpC,MAAM,SAAS,GAAG,IAAI,OAAO,CAAC,WAAW,CAAC,CAAC,WAAW,CACpD,mEAAmE,CACpE,CAAA;IAED,SAAS;SACN,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,6DAA6D,CAAC;SAC1E,MAAM,CAAC,mBAAmB,CAAC,CAAA;IAE9B,SAAS;SACN,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,0DAA0D,CAAC;SACvE,MAAM,CAAC,WAAW,EAAE,8CAA8C,CAAC;SACnE,MAAM,CAAC,qBAAqB,CAAC,CAAA;IAEhC,SAAS;SACN,OAAO,CAAC,eAAe,CAAC;SACxB,WAAW,CAAC,+EAA+E,CAAC;SAC5F,MAAM,CAAC,2BAA2B,CAAC,CAAA;IAEtC,OAAO,SAAS,CAAA;AAClB,CAAC;AAED,kFAAkF;AAClF,OAAO,EACL,OAAO,EACP,SAAS,EACT,eAAe,EACf,uBAAuB,EACvB,yBAAyB,EACzB,+BAA+B,GAChC,MAAM,uBAAuB,CAAA"}
|
package/dist/src/index.js
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
* - setup: Install skillsmith skill for /skillsmith slash command (SMI-824, renamed from install-skill)
|
|
20
20
|
*/
|
|
21
21
|
import { Command } from 'commander';
|
|
22
|
-
import { createSearchCommand, createListCommand, createUpdateCommand, createRemoveCommand, createInitCommand, createValidateCommand, createPublishCommand, createSubagentCommand, createTransformCommand, createMcpInitCommand, createAnalyzeCommand, createRecommendCommand, createSyncCommand, createInstallCommand, createInstallSkillCommand, createLoginCommand, createLogoutCommand, createWhoamiCommand, createDiffCommand, createPinCommand, createUnpinCommand, createAuditCommand, createCreateCommand, createInfoCommand, createImportCommand, createImportLocalCommand, createConfigCommand, createTelemetryCommand, } from './commands/index.js';
|
|
22
|
+
import { createSearchCommand, createListCommand, createUpdateCommand, createRemoveCommand, createInitCommand, createValidateCommand, createPublishCommand, createSubagentCommand, createTransformCommand, createMcpInitCommand, createAnalyzeCommand, createRecommendCommand, createSyncCommand, createInstallCommand, createInstallSkillCommand, createLoginCommand, createLogoutCommand, createWhoamiCommand, createDiffCommand, createPinCommand, createUnpinCommand, createAuditCommand, createCreateCommand, createInfoCommand, createImportCommand, createImportLocalCommand, createConfigCommand, createTelemetryCommand, createInventoryCommand, } from './commands/index.js';
|
|
23
23
|
import { displayStartupHeader } from './utils/license.js';
|
|
24
24
|
import { checkNodeVersion } from './utils/node-version.js';
|
|
25
25
|
import { readFileSync } from 'fs';
|
|
@@ -109,5 +109,7 @@ program.addCommand(createInfoCommand());
|
|
|
109
109
|
program.addCommand(createConfigCommand());
|
|
110
110
|
// SMI-5021 Wave 3: telemetry opt-in + Claude Code hook management
|
|
111
111
|
program.addCommand(createTelemetryCommand());
|
|
112
|
+
// SMI-5392 Wave 3: cross-harness inventory push/status/forget-device
|
|
113
|
+
program.addCommand(createInventoryCommand());
|
|
112
114
|
program.parse();
|
|
113
115
|
//# sourceMappingURL=index.js.map
|
package/dist/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -32,6 +32,48 @@ export interface InstalledSkill {
|
|
|
32
32
|
* callers can render "installed via Cursor" badges.
|
|
33
33
|
*/
|
|
34
34
|
export declare function getSkillsFromDirectory(skillsDir: string, dbPath?: string, installedVia?: ClientId | 'local'): Promise<InstalledSkill[]>;
|
|
35
|
+
/**
|
|
36
|
+
* Per-harness/skill entry produced by {@link getInstalledSkillsPerHarness}.
|
|
37
|
+
* Feeds the cross-harness inventory builder (SMI-5390).
|
|
38
|
+
*
|
|
39
|
+
* `contentHash` is the sha256 hex digest of the skill's raw SKILL.md
|
|
40
|
+
* content — used by the inventory service for registry drift detection.
|
|
41
|
+
* It is `null` when SKILL.md is absent or unreadable.
|
|
42
|
+
*/
|
|
43
|
+
export interface HarnessSkillEntry {
|
|
44
|
+
/** Which harness directory the skill was found under. */
|
|
45
|
+
harness: ClientId | 'local';
|
|
46
|
+
/**
|
|
47
|
+
* Skill identifier: the `id` front-matter field when present (conventionally
|
|
48
|
+
* `author/name`), falling back to the `name` field, then the directory name.
|
|
49
|
+
*/
|
|
50
|
+
skillId: string;
|
|
51
|
+
/** Installed version string, or `null` if absent. */
|
|
52
|
+
version: string | null;
|
|
53
|
+
/** sha256 hex digest of SKILL.md content; `null` if unreadable. */
|
|
54
|
+
contentHash: string | null;
|
|
55
|
+
/** Absolute path to the skill directory. */
|
|
56
|
+
path: string;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Returns one {@link HarnessSkillEntry} per (harness × skill) observed on
|
|
60
|
+
* disk, deduplicated by realpath only.
|
|
61
|
+
*
|
|
62
|
+
* Unlike {@link getInstalledSkills}, this function:
|
|
63
|
+
* - Does **not** deduplicate by skill name — the same skill present under two
|
|
64
|
+
* distinct harness directories appears as two rows (different `path`).
|
|
65
|
+
* - Does deduplicate by realpath — a symlinked alias such as
|
|
66
|
+
* `~/.agents/skills/foo` → `~/.claude/skills/foo` collapses to one row.
|
|
67
|
+
* - Enriches each surviving entry with a sha256 `contentHash` computed from
|
|
68
|
+
* the SKILL.md content, for registry drift detection.
|
|
69
|
+
*
|
|
70
|
+
* Precedence order (first realpath wins when a symlink is detected): local
|
|
71
|
+
* (repo) > claude-code > cursor > copilot > windsurf > agents. Inherits the
|
|
72
|
+
* SMI-4578 ordering so local overrides are still respected.
|
|
73
|
+
*
|
|
74
|
+
* @see SMI-5390
|
|
75
|
+
*/
|
|
76
|
+
export declare function getInstalledSkillsPerHarness(): Promise<HarnessSkillEntry[]>;
|
|
35
77
|
/**
|
|
36
78
|
* Get list of installed skills across every client directory.
|
|
37
79
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skills-directory.d.ts","sourceRoot":"","sources":["../../../src/utils/skills-directory.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EAIL,KAAK,SAAS,EACf,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EAIL,KAAK,QAAQ,EACd,MAAM,0BAA0B,CAAA;AAGjC,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,SAAS,EAAE,SAAS,CAAA;IACpB,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,OAAO,CAAA;IACnB;;;;OAIG;IACH,YAAY,EAAE,QAAQ,GAAG,OAAO,CAAA;CACjC;AAiBD;;;;;;;;;;;;GAYG;AACH,wBAAsB,sBAAsB,CAC1C,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,MAAM,EACf,YAAY,GAAE,QAAQ,GAAG,OAA0B,GAClD,OAAO,CAAC,cAAc,EAAE,CAAC,CAsG3B;AAgBD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,kBAAkB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAwCnF"}
|
|
1
|
+
{"version":3,"file":"skills-directory.d.ts","sourceRoot":"","sources":["../../../src/utils/skills-directory.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EAIL,KAAK,SAAS,EACf,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EAIL,KAAK,QAAQ,EACd,MAAM,0BAA0B,CAAA;AAGjC,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,SAAS,EAAE,SAAS,CAAA;IACpB,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,OAAO,CAAA;IACnB;;;;OAIG;IACH,YAAY,EAAE,QAAQ,GAAG,OAAO,CAAA;CACjC;AAiBD;;;;;;;;;;;;GAYG;AACH,wBAAsB,sBAAsB,CAC1C,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,MAAM,EACf,YAAY,GAAE,QAAQ,GAAG,OAA0B,GAClD,OAAO,CAAC,cAAc,EAAE,CAAC,CAsG3B;AAgBD;;;;;;;GAOG;AACH,MAAM,WAAW,iBAAiB;IAChC,yDAAyD;IACzD,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAA;IAC3B;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAA;IACf,qDAAqD;IACrD,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,mEAAmE;IACnE,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,4CAA4C;IAC5C,IAAI,EAAE,MAAM,CAAA;CACb;AAuBD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,4BAA4B,IAAI,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAyCjF;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,kBAAkB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAwCnF"}
|
|
@@ -148,6 +148,82 @@ async function safeRealpath(p) {
|
|
|
148
148
|
return p;
|
|
149
149
|
}
|
|
150
150
|
}
|
|
151
|
+
/**
|
|
152
|
+
* Reads `<skillPath>/SKILL.md`, returns its sha256 hex content hash and the
|
|
153
|
+
* `id` front-matter field. Both are `null` on any read/parse error.
|
|
154
|
+
* @internal
|
|
155
|
+
*/
|
|
156
|
+
async function readSkillMd(skillPath) {
|
|
157
|
+
try {
|
|
158
|
+
const content = await readFile(join(skillPath, 'SKILL.md'), 'utf-8');
|
|
159
|
+
const contentHash = createHash('sha256').update(content, 'utf8').digest('hex');
|
|
160
|
+
const parser = new SkillParser();
|
|
161
|
+
const parsed = parser.parse(content);
|
|
162
|
+
const parsedAny = parsed;
|
|
163
|
+
const skillId = parsedAny['id'] ?? null;
|
|
164
|
+
return { contentHash, skillId };
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
return { contentHash: null, skillId: null };
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Returns one {@link HarnessSkillEntry} per (harness × skill) observed on
|
|
172
|
+
* disk, deduplicated by realpath only.
|
|
173
|
+
*
|
|
174
|
+
* Unlike {@link getInstalledSkills}, this function:
|
|
175
|
+
* - Does **not** deduplicate by skill name — the same skill present under two
|
|
176
|
+
* distinct harness directories appears as two rows (different `path`).
|
|
177
|
+
* - Does deduplicate by realpath — a symlinked alias such as
|
|
178
|
+
* `~/.agents/skills/foo` → `~/.claude/skills/foo` collapses to one row.
|
|
179
|
+
* - Enriches each surviving entry with a sha256 `contentHash` computed from
|
|
180
|
+
* the SKILL.md content, for registry drift detection.
|
|
181
|
+
*
|
|
182
|
+
* Precedence order (first realpath wins when a symlink is detected): local
|
|
183
|
+
* (repo) > claude-code > cursor > copilot > windsurf > agents. Inherits the
|
|
184
|
+
* SMI-4578 ordering so local overrides are still respected.
|
|
185
|
+
*
|
|
186
|
+
* @see SMI-5390
|
|
187
|
+
*/
|
|
188
|
+
export async function getInstalledSkillsPerHarness() {
|
|
189
|
+
const localScan = getSkillsFromDirectory(getLocalSkillsDir(), undefined, 'local');
|
|
190
|
+
const clientScans = CLIENT_IDS.map((client) => getSkillsFromDirectory(CLIENT_NATIVE_PATHS[client], undefined, client));
|
|
191
|
+
const [localSkills, ...clientSkillsLists] = await Promise.all([localScan, ...clientScans]);
|
|
192
|
+
// Same precedence order as getInstalledSkills — local first, then
|
|
193
|
+
// canonical, then remaining clients.
|
|
194
|
+
const ordered = [...localSkills];
|
|
195
|
+
const canonicalIdx = CLIENT_IDS.indexOf(CANONICAL_CLIENT);
|
|
196
|
+
if (canonicalIdx >= 0 && clientSkillsLists[canonicalIdx]) {
|
|
197
|
+
ordered.push(...clientSkillsLists[canonicalIdx]);
|
|
198
|
+
}
|
|
199
|
+
for (let i = 0; i < CLIENT_IDS.length; i++) {
|
|
200
|
+
if (i === canonicalIdx)
|
|
201
|
+
continue;
|
|
202
|
+
const list = clientSkillsLists[i];
|
|
203
|
+
if (list)
|
|
204
|
+
ordered.push(...list);
|
|
205
|
+
}
|
|
206
|
+
// Realpath-only dedup: collapses symlinked aliases (same inode) but keeps
|
|
207
|
+
// the same skill independently installed under two different harnesses as
|
|
208
|
+
// two distinct rows.
|
|
209
|
+
const seenPaths = new Set();
|
|
210
|
+
const out = [];
|
|
211
|
+
for (const skill of ordered) {
|
|
212
|
+
const rp = await safeRealpath(skill.path);
|
|
213
|
+
if (seenPaths.has(rp))
|
|
214
|
+
continue;
|
|
215
|
+
seenPaths.add(rp);
|
|
216
|
+
const { contentHash, skillId: parsedId } = await readSkillMd(skill.path);
|
|
217
|
+
out.push({
|
|
218
|
+
harness: skill.installedVia,
|
|
219
|
+
skillId: parsedId ?? skill.name,
|
|
220
|
+
version: skill.version,
|
|
221
|
+
contentHash,
|
|
222
|
+
path: skill.path,
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
return out;
|
|
226
|
+
}
|
|
151
227
|
/**
|
|
152
228
|
* Get list of installed skills across every client directory.
|
|
153
229
|
*
|