@skillsmith/cli 0.5.12 → 0.6.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 (111) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +92 -2
  3. package/dist/.tsbuildinfo +1 -1
  4. package/dist/src/commands/audit-collisions.d.ts +71 -0
  5. package/dist/src/commands/audit-collisions.d.ts.map +1 -0
  6. package/dist/src/commands/audit-collisions.js +300 -0
  7. package/dist/src/commands/audit-collisions.js.map +1 -0
  8. package/dist/src/commands/audit.d.ts +27 -2
  9. package/dist/src/commands/audit.d.ts.map +1 -1
  10. package/dist/src/commands/audit.js +70 -10
  11. package/dist/src/commands/audit.js.map +1 -1
  12. package/dist/src/commands/audit.test.js +2 -2
  13. package/dist/src/commands/audit.test.js.map +1 -1
  14. package/dist/src/commands/config.d.ts +55 -0
  15. package/dist/src/commands/config.d.ts.map +1 -0
  16. package/dist/src/commands/config.js +211 -0
  17. package/dist/src/commands/config.js.map +1 -0
  18. package/dist/src/commands/create.d.ts +3 -3
  19. package/dist/src/commands/create.d.ts.map +1 -1
  20. package/dist/src/commands/create.js +11 -9
  21. package/dist/src/commands/create.js.map +1 -1
  22. package/dist/src/commands/diff.js +2 -2
  23. package/dist/src/commands/diff.js.map +1 -1
  24. package/dist/src/commands/import-local.d.ts +21 -0
  25. package/dist/src/commands/import-local.d.ts.map +1 -0
  26. package/dist/src/commands/import-local.helpers.d.ts +28 -0
  27. package/dist/src/commands/import-local.helpers.d.ts.map +1 -0
  28. package/dist/src/commands/import-local.helpers.js +166 -0
  29. package/dist/src/commands/import-local.helpers.js.map +1 -0
  30. package/dist/src/commands/import-local.js +265 -0
  31. package/dist/src/commands/import-local.js.map +1 -0
  32. package/dist/src/commands/import-local.types.d.ts +59 -0
  33. package/dist/src/commands/import-local.types.d.ts.map +1 -0
  34. package/dist/src/commands/import-local.types.js +2 -0
  35. package/dist/src/commands/import-local.types.js.map +1 -0
  36. package/dist/src/{import.d.ts → commands/import.d.ts} +11 -0
  37. package/dist/src/commands/import.d.ts.map +1 -0
  38. package/dist/src/{import.js → commands/import.js} +36 -2
  39. package/dist/src/commands/import.js.map +1 -0
  40. package/dist/src/commands/index.d.ts +3 -0
  41. package/dist/src/commands/index.d.ts.map +1 -1
  42. package/dist/src/commands/index.js +6 -0
  43. package/dist/src/commands/index.js.map +1 -1
  44. package/dist/src/commands/install-skill.d.ts.map +1 -1
  45. package/dist/src/commands/install-skill.js +6 -3
  46. package/dist/src/commands/install-skill.js.map +1 -1
  47. package/dist/src/commands/install.d.ts.map +1 -1
  48. package/dist/src/commands/install.js +71 -2
  49. package/dist/src/commands/install.js.map +1 -1
  50. package/dist/src/commands/manage.d.ts.map +1 -1
  51. package/dist/src/commands/manage.js +13 -0
  52. package/dist/src/commands/manage.js.map +1 -1
  53. package/dist/src/commands/recommend.helpers.d.ts +5 -1
  54. package/dist/src/commands/recommend.helpers.d.ts.map +1 -1
  55. package/dist/src/commands/recommend.helpers.js +9 -3
  56. package/dist/src/commands/recommend.helpers.js.map +1 -1
  57. package/dist/src/config.d.ts +6 -1
  58. package/dist/src/config.d.ts.map +1 -1
  59. package/dist/src/config.js +8 -2
  60. package/dist/src/config.js.map +1 -1
  61. package/dist/src/index.d.ts +1 -1
  62. package/dist/src/index.js +10 -28
  63. package/dist/src/index.js.map +1 -1
  64. package/dist/src/templates/mcp-server.template.d.ts +1 -1
  65. package/dist/src/templates/mcp-server.template.d.ts.map +1 -1
  66. package/dist/src/templates/mcp-server.template.js +13 -13
  67. package/dist/src/templates/mcp-server.template.js.map +1 -1
  68. package/dist/src/templates/mcp-server.template.snippets.d.ts +51 -0
  69. package/dist/src/templates/mcp-server.template.snippets.d.ts.map +1 -0
  70. package/dist/src/templates/mcp-server.template.snippets.js +162 -0
  71. package/dist/src/templates/mcp-server.template.snippets.js.map +1 -0
  72. package/dist/src/templates/readme.md.template.d.ts +1 -1
  73. package/dist/src/templates/readme.md.template.d.ts.map +1 -1
  74. package/dist/src/templates/readme.md.template.js +2 -2
  75. package/dist/src/utils/skills-directory.d.ts +26 -7
  76. package/dist/src/utils/skills-directory.d.ts.map +1 -1
  77. package/dist/src/utils/skills-directory.js +75 -30
  78. package/dist/src/utils/skills-directory.js.map +1 -1
  79. package/dist/tests/audit-collisions.test.d.ts +42 -0
  80. package/dist/tests/audit-collisions.test.d.ts.map +1 -0
  81. package/dist/tests/audit-collisions.test.js +370 -0
  82. package/dist/tests/audit-collisions.test.js.map +1 -0
  83. package/dist/tests/audit-restructure.test.d.ts +15 -0
  84. package/dist/tests/audit-restructure.test.d.ts.map +1 -0
  85. package/dist/tests/audit-restructure.test.js +151 -0
  86. package/dist/tests/audit-restructure.test.js.map +1 -0
  87. package/dist/tests/config.test.d.ts +33 -0
  88. package/dist/tests/config.test.d.ts.map +1 -0
  89. package/dist/tests/config.test.js +240 -0
  90. package/dist/tests/config.test.js.map +1 -0
  91. package/dist/tests/install-multi-client.test.d.ts +2 -0
  92. package/dist/tests/install-multi-client.test.d.ts.map +1 -0
  93. package/dist/tests/install-multi-client.test.js +202 -0
  94. package/dist/tests/install-multi-client.test.js.map +1 -0
  95. package/dist/tests/integration/import-local.test.d.ts +2 -0
  96. package/dist/tests/integration/import-local.test.d.ts.map +1 -0
  97. package/dist/tests/integration/import-local.test.js +158 -0
  98. package/dist/tests/integration/import-local.test.js.map +1 -0
  99. package/dist/tests/mcp-server-template.test.js +21 -0
  100. package/dist/tests/mcp-server-template.test.js.map +1 -1
  101. package/dist/tests/skills-directory.test.d.ts +2 -0
  102. package/dist/tests/skills-directory.test.d.ts.map +1 -0
  103. package/dist/tests/skills-directory.test.js +97 -0
  104. package/dist/tests/skills-directory.test.js.map +1 -0
  105. package/dist/tests/unit/import-local.helpers.test.d.ts +2 -0
  106. package/dist/tests/unit/import-local.helpers.test.d.ts.map +1 -0
  107. package/dist/tests/unit/import-local.helpers.test.js +96 -0
  108. package/dist/tests/unit/import-local.helpers.test.js.map +1 -0
  109. package/package.json +9 -3
  110. package/dist/src/import.d.ts.map +0 -1
  111. package/dist/src/import.js.map +0 -1
@@ -0,0 +1,370 @@
1
+ /**
2
+ * @fileoverview SMI-4590 Wave 4 PR 5/6 — `sklx audit collisions` tests
3
+ * @module @skillsmith/cli/tests/audit-collisions
4
+ *
5
+ * Coverage:
6
+ *
7
+ * Typed-confirmation gate (`requireConfirmationPhrase`) — load-bearing per
8
+ * plan §235-239. Strict literal equality, NO normalization.
9
+ * 1. Exact phrase ('APPLY ALL') — RESOLVES.
10
+ * 2. Single-letter ('Y') — REJECTS.
11
+ * 3. Lowercase word ('yes') — REJECTS.
12
+ * 4. Lowercase phrase ('apply all') — REJECTS.
13
+ * 5. No-space variant ('APPLYALL') — REJECTS.
14
+ * 6. Trailing whitespace ('APPLY ALL ') — REJECTS (no trim).
15
+ * 7. Empty string — REJECTS.
16
+ *
17
+ * Both interactive (TTY) and piped-stdin paths route through the same
18
+ * `@inquirer/prompts` `input()` call, so the rejection invariant holds for
19
+ * both. We mock `input` to assert the contract — the prompt library
20
+ * receives the answer verbatim and our code applies strict equality.
21
+ *
22
+ * Interactive prompt loop (`runInteractiveLoop`):
23
+ * 8. 'apply' choice → applyOneSuggestion called, status=applied.
24
+ * 9. 'skip' choice → outcome recorded as skipped, no apply call.
25
+ * 10. 'edit' choice → input prompts for custom name, applyRename
26
+ * receives `customName`.
27
+ * 11. 'quit' choice → loop terminates early; remaining suggestions
28
+ * are NOT processed.
29
+ * 12. Empty suggestion list → prints "No collisions found." and returns.
30
+ *
31
+ * Reset-ledger flow (`runResetLedger`):
32
+ * 13. Backs up an existing ledger to `~/.skillsmith/backups/ledger-*.json`
33
+ * BEFORE clearing.
34
+ * 14. No backup file when no prior ledger exists.
35
+ * 15. Confirmation phrase mismatch → throws, NO writeLedger call.
36
+ *
37
+ * `--json` output (`runAuditCollisions`):
38
+ * 16. JSON mode prints `RunInventoryAuditResult` to stdout, no prompts,
39
+ * no apply.
40
+ */
41
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
42
+ import * as fs from 'node:fs';
43
+ import * as os from 'node:os';
44
+ import { join } from 'node:path';
45
+ // ============================================================================
46
+ // Mock setup — must precede source imports.
47
+ // ============================================================================
48
+ const mocks = vi.hoisted(() => ({
49
+ input: vi.fn(),
50
+ select: vi.fn(),
51
+ applyRename: vi.fn(),
52
+ readLedger: vi.fn(),
53
+ writeLedger: vi.fn(),
54
+ runInventoryAudit: vi.fn(),
55
+ getLicenseStatus: vi.fn(),
56
+ }));
57
+ vi.mock('@inquirer/prompts', () => ({
58
+ input: (opts) => mocks.input(opts),
59
+ select: (opts) => mocks.select(opts),
60
+ }));
61
+ vi.mock('@skillsmith/mcp-server/audit', () => ({
62
+ applyRename: (opts) => mocks.applyRename(opts),
63
+ readLedger: () => mocks.readLedger(),
64
+ writeLedger: (data) => mocks.writeLedger(data),
65
+ runInventoryAudit: (opts) => mocks.runInventoryAudit(opts),
66
+ NAMESPACE_OVERRIDES_CURRENT_VERSION: 1,
67
+ }));
68
+ vi.mock('../src/utils/license.js', () => ({
69
+ getLicenseStatus: () => mocks.getLicenseStatus(),
70
+ }));
71
+ import { requireConfirmationPhrase, runResetLedger, runInteractiveLoop, runAuditCollisions, APPLY_ALL_PHRASE, RESET_LEDGER_PHRASE, CONFIRMATION_REJECTED_MESSAGE, } from '../src/commands/audit-collisions.js';
72
+ // ============================================================================
73
+ // Helpers
74
+ // ============================================================================
75
+ function makeSuggestion(id, currentName, suggested) {
76
+ return {
77
+ collisionId: id,
78
+ currentName,
79
+ suggested,
80
+ reason: `mock-reason-${id}`,
81
+ targetMtime: 0,
82
+ siblingMtime: 0,
83
+ };
84
+ }
85
+ function makeAudit(overrides = {}) {
86
+ return {
87
+ auditId: '01HMOCKAUDITID000000000000',
88
+ reportPath: '/tmp/audit-report.md',
89
+ renameSuggestions: [],
90
+ ...overrides,
91
+ };
92
+ }
93
+ // ============================================================================
94
+ // Tests
95
+ // ============================================================================
96
+ describe('SMI-4590 Wave 4 PR 5/6 — sklx audit collisions', () => {
97
+ let stdoutSpy;
98
+ beforeEach(() => {
99
+ vi.clearAllMocks();
100
+ mocks.applyRename.mockResolvedValue({ success: true, summary: 'renamed' });
101
+ mocks.readLedger.mockResolvedValue({ version: 1, overrides: [] });
102
+ mocks.writeLedger.mockResolvedValue(undefined);
103
+ mocks.getLicenseStatus.mockResolvedValue({ tier: 'team' });
104
+ stdoutSpy = vi.spyOn(console, 'log').mockImplementation(() => { });
105
+ });
106
+ afterEach(() => {
107
+ stdoutSpy.mockRestore();
108
+ });
109
+ describe('typed-confirmation gate (plan §235-239)', () => {
110
+ it('resolves on exact APPLY ALL match', async () => {
111
+ mocks.input.mockResolvedValueOnce(APPLY_ALL_PHRASE);
112
+ await expect(requireConfirmationPhrase(APPLY_ALL_PHRASE, 'msg')).resolves.toBeUndefined();
113
+ });
114
+ it('rejects single-letter Y', async () => {
115
+ mocks.input.mockResolvedValueOnce('Y');
116
+ await expect(requireConfirmationPhrase(APPLY_ALL_PHRASE, 'msg')).rejects.toThrow(CONFIRMATION_REJECTED_MESSAGE);
117
+ });
118
+ it('rejects lowercase yes', async () => {
119
+ mocks.input.mockResolvedValueOnce('yes');
120
+ await expect(requireConfirmationPhrase(APPLY_ALL_PHRASE, 'msg')).rejects.toThrow(CONFIRMATION_REJECTED_MESSAGE);
121
+ });
122
+ it('rejects lowercase apply all (case-sensitive)', async () => {
123
+ mocks.input.mockResolvedValueOnce('apply all');
124
+ await expect(requireConfirmationPhrase(APPLY_ALL_PHRASE, 'msg')).rejects.toThrow(CONFIRMATION_REJECTED_MESSAGE);
125
+ });
126
+ it('rejects no-space APPLYALL', async () => {
127
+ mocks.input.mockResolvedValueOnce('APPLYALL');
128
+ await expect(requireConfirmationPhrase(APPLY_ALL_PHRASE, 'msg')).rejects.toThrow(CONFIRMATION_REJECTED_MESSAGE);
129
+ });
130
+ it('rejects trailing whitespace (no trim)', async () => {
131
+ mocks.input.mockResolvedValueOnce('APPLY ALL ');
132
+ await expect(requireConfirmationPhrase(APPLY_ALL_PHRASE, 'msg')).rejects.toThrow(CONFIRMATION_REJECTED_MESSAGE);
133
+ });
134
+ it('rejects empty string', async () => {
135
+ mocks.input.mockResolvedValueOnce('');
136
+ await expect(requireConfirmationPhrase(APPLY_ALL_PHRASE, 'msg')).rejects.toThrow(CONFIRMATION_REJECTED_MESSAGE);
137
+ });
138
+ it('resolves on exact RESET LEDGER match', async () => {
139
+ mocks.input.mockResolvedValueOnce(RESET_LEDGER_PHRASE);
140
+ await expect(requireConfirmationPhrase(RESET_LEDGER_PHRASE, 'msg')).resolves.toBeUndefined();
141
+ });
142
+ });
143
+ describe('interactive prompt loop choices', () => {
144
+ it("'apply' choice triggers applyRename", async () => {
145
+ const audit = makeAudit({
146
+ renameSuggestions: [makeSuggestion('c1', 'foo/bar', 'foo/bar-2')],
147
+ });
148
+ mocks.select.mockResolvedValueOnce('apply');
149
+ await runInteractiveLoop(audit);
150
+ expect(mocks.applyRename).toHaveBeenCalledTimes(1);
151
+ expect(mocks.applyRename.mock.calls[0]?.[0]).toMatchObject({
152
+ request: { action: 'apply', auditId: audit.auditId },
153
+ });
154
+ });
155
+ it("'skip' choice records skipped outcome and does NOT call applyRename", async () => {
156
+ const audit = makeAudit({
157
+ renameSuggestions: [makeSuggestion('c1', 'foo/bar', 'foo/bar-2')],
158
+ });
159
+ mocks.select.mockResolvedValueOnce('skip');
160
+ await runInteractiveLoop(audit);
161
+ expect(mocks.applyRename).not.toHaveBeenCalled();
162
+ });
163
+ it("'edit' choice forwards customName to applyRename", async () => {
164
+ const audit = makeAudit({
165
+ renameSuggestions: [makeSuggestion('c1', 'foo/bar', 'foo/bar-2')],
166
+ });
167
+ mocks.select.mockResolvedValueOnce('edit');
168
+ mocks.input.mockResolvedValueOnce(' custom-renamed ');
169
+ await runInteractiveLoop(audit);
170
+ expect(mocks.applyRename).toHaveBeenCalledWith({
171
+ suggestion: expect.objectContaining({ collisionId: 'c1' }),
172
+ request: {
173
+ action: 'apply',
174
+ auditId: audit.auditId,
175
+ customName: 'custom-renamed',
176
+ },
177
+ });
178
+ });
179
+ it("'quit' choice terminates the loop early", async () => {
180
+ const audit = makeAudit({
181
+ renameSuggestions: [
182
+ makeSuggestion('c1', 'foo/bar', 'foo/bar-2'),
183
+ makeSuggestion('c2', 'foo/baz', 'foo/baz-2'),
184
+ ],
185
+ });
186
+ mocks.select.mockResolvedValueOnce('quit');
187
+ await runInteractiveLoop(audit);
188
+ // Loop aborted before processing any suggestion → applyRename never called.
189
+ expect(mocks.applyRename).not.toHaveBeenCalled();
190
+ // And select was only consulted once (for the first suggestion before quit).
191
+ expect(mocks.select).toHaveBeenCalledTimes(1);
192
+ });
193
+ it('empty suggestions prints No collisions found and returns', async () => {
194
+ const audit = makeAudit({ renameSuggestions: [] });
195
+ await runInteractiveLoop(audit);
196
+ expect(mocks.select).not.toHaveBeenCalled();
197
+ expect(mocks.applyRename).not.toHaveBeenCalled();
198
+ });
199
+ });
200
+ describe('--reset-ledger flow', () => {
201
+ let tmpHome;
202
+ let originalHome;
203
+ beforeEach(() => {
204
+ tmpHome = fs.mkdtempSync(join(os.tmpdir(), 'sklx-test-home-'));
205
+ originalHome = process.env['HOME'];
206
+ process.env['HOME'] = tmpHome;
207
+ });
208
+ afterEach(() => {
209
+ if (originalHome !== undefined) {
210
+ process.env['HOME'] = originalHome;
211
+ }
212
+ else {
213
+ delete process.env['HOME'];
214
+ }
215
+ fs.rmSync(tmpHome, { recursive: true, force: true });
216
+ });
217
+ it('backs up an existing ledger before clearing', async () => {
218
+ const ledgerDir = join(tmpHome, '.skillsmith');
219
+ fs.mkdirSync(ledgerDir, { recursive: true });
220
+ const ledgerFile = join(ledgerDir, 'namespace-overrides.json');
221
+ fs.writeFileSync(ledgerFile, '{"version":1,"overrides":[{"id":"x"}]}', 'utf-8');
222
+ mocks.input.mockResolvedValueOnce(RESET_LEDGER_PHRASE);
223
+ await runResetLedger();
224
+ // Backup file written.
225
+ const backupsDir = join(ledgerDir, 'backups');
226
+ expect(fs.existsSync(backupsDir)).toBe(true);
227
+ const entries = fs.readdirSync(backupsDir).filter((f) => f.startsWith('ledger-'));
228
+ expect(entries.length).toBe(1);
229
+ // Backup contains the original payload.
230
+ const backup = fs.readFileSync(join(backupsDir, entries[0]), 'utf-8');
231
+ expect(backup).toContain('"id":"x"');
232
+ // writeLedger called with empty overrides.
233
+ expect(mocks.writeLedger).toHaveBeenCalledWith({
234
+ version: 1,
235
+ overrides: [],
236
+ });
237
+ });
238
+ it('no backup file when no prior ledger exists', async () => {
239
+ mocks.input.mockResolvedValueOnce(RESET_LEDGER_PHRASE);
240
+ await runResetLedger();
241
+ const backupsDir = join(tmpHome, '.skillsmith', 'backups');
242
+ // backupsDir may not exist at all when no source ledger present.
243
+ const entries = fs.existsSync(backupsDir) ? fs.readdirSync(backupsDir) : [];
244
+ expect(entries.length).toBe(0);
245
+ expect(mocks.writeLedger).toHaveBeenCalledWith({
246
+ version: 1,
247
+ overrides: [],
248
+ });
249
+ });
250
+ it('confirmation mismatch throws and does NOT call writeLedger', async () => {
251
+ mocks.input.mockResolvedValueOnce('reset ledger'); // wrong case
252
+ await expect(runResetLedger()).rejects.toThrow(CONFIRMATION_REJECTED_MESSAGE);
253
+ expect(mocks.writeLedger).not.toHaveBeenCalled();
254
+ });
255
+ });
256
+ describe('--reset-ledger preflight (plan §297)', () => {
257
+ let tmpHome;
258
+ let originalHome;
259
+ beforeEach(() => {
260
+ tmpHome = fs.mkdtempSync(join(os.tmpdir(), 'sklx-test-home-'));
261
+ originalHome = process.env['HOME'];
262
+ process.env['HOME'] = tmpHome;
263
+ });
264
+ afterEach(() => {
265
+ if (originalHome !== undefined) {
266
+ process.env['HOME'] = originalHome;
267
+ }
268
+ else {
269
+ delete process.env['HOME'];
270
+ }
271
+ fs.rmSync(tmpHome, { recursive: true, force: true });
272
+ });
273
+ it('reads the ledger BEFORE prompting (so version_unsupported errors surface first)', async () => {
274
+ // Simulate a higher-version ledger by having readLedger throw.
275
+ const versionError = new Error('namespace.ledger.version_unsupported');
276
+ mocks.readLedger.mockRejectedValueOnce(versionError);
277
+ await expect(runAuditCollisions({
278
+ deep: false,
279
+ json: false,
280
+ applyAll: false,
281
+ reportOnly: false,
282
+ resetLedger: true,
283
+ })).rejects.toThrow('namespace.ledger.version_unsupported');
284
+ // The user was never prompted because readLedger threw first.
285
+ expect(mocks.input).not.toHaveBeenCalled();
286
+ expect(mocks.writeLedger).not.toHaveBeenCalled();
287
+ });
288
+ });
289
+ describe('--apply-all end-to-end (typed gate + sequential apply)', () => {
290
+ it('applies every suggestion sequentially after APPLY ALL phrase', async () => {
291
+ const audit = makeAudit({
292
+ renameSuggestions: [
293
+ makeSuggestion('c1', 'a/x', 'a/x-2'),
294
+ makeSuggestion('c2', 'a/y', 'a/y-2'),
295
+ makeSuggestion('c3', 'a/z', 'a/z-2'),
296
+ ],
297
+ });
298
+ mocks.runInventoryAudit.mockResolvedValueOnce(audit);
299
+ mocks.input.mockResolvedValueOnce(APPLY_ALL_PHRASE);
300
+ await runAuditCollisions({
301
+ deep: false,
302
+ json: false,
303
+ applyAll: true,
304
+ reportOnly: false,
305
+ resetLedger: false,
306
+ });
307
+ // applyRename invoked once per suggestion.
308
+ expect(mocks.applyRename).toHaveBeenCalledTimes(3);
309
+ expect(mocks.select).not.toHaveBeenCalled();
310
+ });
311
+ it('rejects --apply-all when phrase is wrong; no applyRename calls', async () => {
312
+ const audit = makeAudit({
313
+ renameSuggestions: [makeSuggestion('c1', 'a/x', 'a/x-2')],
314
+ });
315
+ mocks.runInventoryAudit.mockResolvedValueOnce(audit);
316
+ mocks.input.mockResolvedValueOnce('apply all'); // wrong case
317
+ await expect(runAuditCollisions({
318
+ deep: false,
319
+ json: false,
320
+ applyAll: true,
321
+ reportOnly: false,
322
+ resetLedger: false,
323
+ })).rejects.toThrow(CONFIRMATION_REJECTED_MESSAGE);
324
+ expect(mocks.applyRename).not.toHaveBeenCalled();
325
+ });
326
+ });
327
+ describe('interactive default is `skip` (regression guard for inattentive Enter-press)', () => {
328
+ it('defaults the select prompt to `skip` not `apply`', async () => {
329
+ const audit = makeAudit({
330
+ renameSuggestions: [makeSuggestion('c1', 'a/x', 'a/x-2')],
331
+ });
332
+ // Capture the options passed to select.
333
+ let capturedOpts;
334
+ mocks.select.mockImplementationOnce((opts) => {
335
+ capturedOpts = opts;
336
+ return Promise.resolve('skip');
337
+ });
338
+ await runInteractiveLoop(audit);
339
+ expect(capturedOpts).toBeDefined();
340
+ expect(capturedOpts?.default).toBe('skip');
341
+ });
342
+ });
343
+ describe('--json output', () => {
344
+ it('prints RunInventoryAuditResult JSON and skips prompts', async () => {
345
+ const audit = makeAudit({
346
+ renameSuggestions: [makeSuggestion('c1', 'foo/bar', 'foo/bar-2')],
347
+ });
348
+ mocks.runInventoryAudit.mockResolvedValueOnce(audit);
349
+ await runAuditCollisions({
350
+ deep: false,
351
+ json: true,
352
+ applyAll: false,
353
+ reportOnly: false,
354
+ resetLedger: false,
355
+ });
356
+ // No prompts consulted.
357
+ expect(mocks.input).not.toHaveBeenCalled();
358
+ expect(mocks.select).not.toHaveBeenCalled();
359
+ expect(mocks.applyRename).not.toHaveBeenCalled();
360
+ // Last console.log call should contain serialized JSON of audit.
361
+ const calls = stdoutSpy.mock.calls.map((c) => String(c[0] ?? ''));
362
+ const jsonOutput = calls.find((c) => c.includes(audit.auditId));
363
+ expect(jsonOutput).toBeDefined();
364
+ // Parse and check shape.
365
+ const parsed = JSON.parse(jsonOutput);
366
+ expect(parsed.auditId).toBe(audit.auditId);
367
+ });
368
+ });
369
+ });
370
+ //# sourceMappingURL=audit-collisions.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-collisions.test.js","sourceRoot":"","sources":["../../tests/audit-collisions.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * @fileoverview SMI-4590 Step 0a — `sklx audit` restructure tests
3
+ * @module @skillsmith/cli/tests/audit-restructure
4
+ *
5
+ * Asserts the parent `audit` command surface:
6
+ * - `sklx audit advisories` is registered as a subcommand.
7
+ * - `sklx audit <skill-id>` (positional fallback) emits the deprecation
8
+ * warning and forwards to the same advisories handler.
9
+ * - `sklx audit` with no args prints parent help.
10
+ *
11
+ * Behavioral coverage of `runAdvisoriesAudit` itself stays under
12
+ * `audit.ts`'s existing test surface — these tests verify the wiring only.
13
+ */
14
+ export {};
15
+ //# sourceMappingURL=audit-restructure.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-restructure.test.d.ts","sourceRoot":"","sources":["../../tests/audit-restructure.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG"}
@@ -0,0 +1,151 @@
1
+ /**
2
+ * @fileoverview SMI-4590 Step 0a — `sklx audit` restructure tests
3
+ * @module @skillsmith/cli/tests/audit-restructure
4
+ *
5
+ * Asserts the parent `audit` command surface:
6
+ * - `sklx audit advisories` is registered as a subcommand.
7
+ * - `sklx audit <skill-id>` (positional fallback) emits the deprecation
8
+ * warning and forwards to the same advisories handler.
9
+ * - `sklx audit` with no args prints parent help.
10
+ *
11
+ * Behavioral coverage of `runAdvisoriesAudit` itself stays under
12
+ * `audit.ts`'s existing test surface — these tests verify the wiring only.
13
+ */
14
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
15
+ import { Command } from 'commander';
16
+ // ============================================================================
17
+ // Mock setup — must precede source imports so commander.action() bodies see
18
+ // the mocked deps when they execute.
19
+ // ============================================================================
20
+ const mocks = vi.hoisted(() => ({
21
+ requireTier: vi.fn(async (_tier) => undefined),
22
+ createDatabaseAsync: vi.fn(async (_path) => ({
23
+ close: () => undefined,
24
+ })),
25
+ initializeSchema: vi.fn((_db) => undefined),
26
+ AdvisoryRepositoryCtor: vi.fn((_db) => undefined),
27
+ getActiveAdvisories: vi.fn(() => []),
28
+ }));
29
+ vi.mock('@skillsmith/core', () => ({
30
+ createDatabaseAsync: (path) => mocks.createDatabaseAsync(path),
31
+ initializeSchema: (db) => mocks.initializeSchema(db),
32
+ AdvisoryRepository: function AdvisoryRepository(db) {
33
+ mocks.AdvisoryRepositoryCtor(db);
34
+ this.getActiveAdvisories =
35
+ mocks.getActiveAdvisories;
36
+ },
37
+ }));
38
+ vi.mock('../src/utils/require-tier.js', () => ({
39
+ requireTier: (tier) => mocks.requireTier(tier),
40
+ }));
41
+ import { createAuditCommand, createAuditAdvisoriesSubcommand, AUDIT_FLAT_DEPRECATION_NOTICE, } from '../src/commands/audit.js';
42
+ function setupDbStub() {
43
+ const db = { close: vi.fn() };
44
+ mocks.createDatabaseAsync.mockResolvedValue(db);
45
+ return db;
46
+ }
47
+ // ============================================================================
48
+ // Tests
49
+ // ============================================================================
50
+ describe('SMI-4590 Step 0a — sklx audit restructure', () => {
51
+ let stderrSpy;
52
+ let stdoutSpy;
53
+ let exitSpy;
54
+ beforeEach(() => {
55
+ vi.clearAllMocks();
56
+ mocks.requireTier.mockResolvedValue(undefined);
57
+ mocks.getActiveAdvisories.mockReturnValue([]);
58
+ stderrSpy = vi.spyOn(console, 'error').mockImplementation(() => { });
59
+ stdoutSpy = vi.spyOn(console, 'log').mockImplementation(() => { });
60
+ // process.exit must throw so test bodies never actually exit the runner.
61
+ exitSpy = vi.spyOn(process, 'exit').mockImplementation((() => {
62
+ throw new Error('process.exit called');
63
+ }));
64
+ });
65
+ afterEach(() => {
66
+ stderrSpy.mockRestore();
67
+ stdoutSpy.mockRestore();
68
+ exitSpy.mockRestore();
69
+ });
70
+ describe('parent command shape', () => {
71
+ it('registers `audit` as a parent command with description', () => {
72
+ const audit = createAuditCommand();
73
+ expect(audit.name()).toBe('audit');
74
+ expect(audit.description()).toMatch(/audit/i);
75
+ });
76
+ it('registers `advisories` as a subcommand', () => {
77
+ const audit = createAuditCommand();
78
+ const subcommandNames = audit.commands.map((c) => c.name());
79
+ expect(subcommandNames).toContain('advisories');
80
+ });
81
+ });
82
+ describe('`sklx audit advisories` (canonical)', () => {
83
+ it('runs the advisories handler', async () => {
84
+ setupDbStub();
85
+ const audit = createAuditCommand();
86
+ const root = new Command().exitOverride();
87
+ root.addCommand(audit);
88
+ await root.parseAsync(['node', 'sklx', 'audit', 'advisories']);
89
+ expect(mocks.requireTier).toHaveBeenCalledWith('team');
90
+ expect(mocks.createDatabaseAsync).toHaveBeenCalled();
91
+ expect(mocks.AdvisoryRepositoryCtor).toHaveBeenCalled();
92
+ });
93
+ it('does NOT emit the deprecation warning', async () => {
94
+ setupDbStub();
95
+ const audit = createAuditCommand();
96
+ const root = new Command().exitOverride();
97
+ root.addCommand(audit);
98
+ await root.parseAsync(['node', 'sklx', 'audit', 'advisories']);
99
+ const warnings = stderrSpy.mock.calls.flat().filter((arg) => typeof arg === 'string' && arg.includes('DEPRECATED'));
100
+ expect(warnings).toHaveLength(0);
101
+ });
102
+ });
103
+ describe('`sklx audit <skill-id>` deprecation alias', () => {
104
+ it('emits the deprecation warning to stderr', async () => {
105
+ setupDbStub();
106
+ const audit = createAuditCommand();
107
+ const root = new Command().exitOverride();
108
+ root.addCommand(audit);
109
+ await root.parseAsync(['node', 'sklx', 'audit', 'some/skill-id']);
110
+ const warnings = stderrSpy.mock.calls.flat().filter((arg) => typeof arg === 'string' && arg.includes(AUDIT_FLAT_DEPRECATION_NOTICE));
111
+ expect(warnings.length).toBeGreaterThan(0);
112
+ });
113
+ it('forwards to the same advisories handler', async () => {
114
+ setupDbStub();
115
+ const audit = createAuditCommand();
116
+ const root = new Command().exitOverride();
117
+ root.addCommand(audit);
118
+ await root.parseAsync(['node', 'sklx', 'audit', 'some/skill-id']);
119
+ expect(mocks.requireTier).toHaveBeenCalledWith('team');
120
+ expect(mocks.createDatabaseAsync).toHaveBeenCalled();
121
+ });
122
+ it('mentions the canonical `audit advisories` form in the warning', () => {
123
+ expect(AUDIT_FLAT_DEPRECATION_NOTICE).toMatch(/audit advisories/);
124
+ });
125
+ it('flags the alias as removed in the next minor', () => {
126
+ expect(AUDIT_FLAT_DEPRECATION_NOTICE).toMatch(/next minor/i);
127
+ });
128
+ });
129
+ describe('`sklx audit` with no args', () => {
130
+ it('prints help (no advisories handler invocation)', async () => {
131
+ const audit = createAuditCommand();
132
+ const root = new Command().exitOverride();
133
+ root.addCommand(audit);
134
+ // commander's `.help()` calls process.exit; our spy throws.
135
+ await expect(root.parseAsync(['node', 'sklx', 'audit'])).rejects.toThrow();
136
+ expect(mocks.requireTier).not.toHaveBeenCalled();
137
+ expect(mocks.createDatabaseAsync).not.toHaveBeenCalled();
138
+ });
139
+ });
140
+ describe('subcommand factory exports (regression guard)', () => {
141
+ it('createAuditAdvisoriesSubcommand returns a Command named `advisories`', () => {
142
+ const cmd = createAuditAdvisoriesSubcommand();
143
+ expect(cmd.name()).toBe('advisories');
144
+ });
145
+ it('createAuditCommand returns a Command named `audit`', () => {
146
+ const cmd = createAuditCommand();
147
+ expect(cmd.name()).toBe('audit');
148
+ });
149
+ });
150
+ });
151
+ //# sourceMappingURL=audit-restructure.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-restructure.test.js","sourceRoot":"","sources":["../../tests/audit-restructure.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * @fileoverview SMI-4590 Wave 4 PR 5/6 — `sklx config get/set audit_mode` tests
3
+ * @module @skillsmith/cli/tests/config
4
+ *
5
+ * Coverage (plan §810-813 — load-bearing tier-revalidation security tests):
6
+ *
7
+ * Tier revalidation matrix — the `set` path MUST refuse a write when
8
+ * `tierAllowsAuditMode(tier, mode)` returns false. No file IO occurs on
9
+ * rejection; the existing config (if any) stays intact.
10
+ *
11
+ * 1. community + power_user → audit.mode.tier_ineligible, NO write
12
+ * 2. community + governance → audit.mode.tier_ineligible, NO write
13
+ * 3. individual + power_user → audit.mode.tier_ineligible, NO write
14
+ * 4. individual + governance → audit.mode.tier_ineligible, NO write
15
+ * 5. team + power_user → SUCCESS, file written
16
+ * 6. team + governance → audit.mode.tier_ineligible (Enterprise-only)
17
+ * 7. enterprise + governance → SUCCESS, file written
18
+ *
19
+ * Value validation:
20
+ * 8. any tier + invalid_value → audit.mode.invalid_value, NO write
21
+ * 9. any tier + preventative → SUCCESS for every tier
22
+ * 10. any tier + off → SUCCESS for every tier
23
+ *
24
+ * Unsupported keys:
25
+ * 11. set with unknown key → config.unsupported_key, NO write
26
+ * 12. get with unknown key → config.unsupported_key
27
+ *
28
+ * Get path:
29
+ * 13. get audit_mode reads existing file value when present
30
+ * 14. get audit_mode falls back to tier default when unset
31
+ */
32
+ export {};
33
+ //# sourceMappingURL=config.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.test.d.ts","sourceRoot":"","sources":["../../tests/config.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG"}