@skillsmith/cli 0.6.2 → 0.6.4
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 +18 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/src/commands/__meta__/telemetry-coverage.test.d.ts +20 -0
- package/dist/src/commands/__meta__/telemetry-coverage.test.d.ts.map +1 -0
- package/dist/src/commands/__meta__/telemetry-coverage.test.js +118 -0
- package/dist/src/commands/__meta__/telemetry-coverage.test.js.map +1 -0
- package/dist/src/commands/ab-test.d.ts +1 -0
- package/dist/src/commands/ab-test.d.ts.map +1 -1
- package/dist/src/commands/ab-test.js +17 -8
- package/dist/src/commands/ab-test.js.map +1 -1
- package/dist/src/commands/analyze.d.ts +1 -0
- package/dist/src/commands/analyze.d.ts.map +1 -1
- package/dist/src/commands/analyze.js +32 -23
- package/dist/src/commands/analyze.js.map +1 -1
- package/dist/src/commands/audit-collisions.d.ts +1 -4
- package/dist/src/commands/audit-collisions.d.ts.map +1 -1
- package/dist/src/commands/audit-collisions.js +32 -23
- package/dist/src/commands/audit-collisions.js.map +1 -1
- package/dist/src/commands/audit-sources.action.d.ts +37 -0
- package/dist/src/commands/audit-sources.action.d.ts.map +1 -0
- package/dist/src/commands/audit-sources.action.js +300 -0
- package/dist/src/commands/audit-sources.action.js.map +1 -0
- package/dist/src/commands/audit-sources.d.ts +37 -0
- package/dist/src/commands/audit-sources.d.ts.map +1 -0
- package/dist/src/commands/audit-sources.js +55 -0
- package/dist/src/commands/audit-sources.js.map +1 -0
- package/dist/src/commands/audit-sources.test.d.ts +9 -0
- package/dist/src/commands/audit-sources.test.d.ts.map +1 -0
- package/dist/src/commands/audit-sources.test.js +228 -0
- package/dist/src/commands/audit-sources.test.js.map +1 -0
- package/dist/src/commands/audit.d.ts +2 -6
- package/dist/src/commands/audit.d.ts.map +1 -1
- package/dist/src/commands/audit.js +52 -31
- package/dist/src/commands/audit.js.map +1 -1
- package/dist/src/commands/author/index.d.ts +2 -1
- package/dist/src/commands/author/index.d.ts.map +1 -1
- package/dist/src/commands/author/index.js +4 -1
- package/dist/src/commands/author/index.js.map +1 -1
- package/dist/src/commands/author/init.action.d.ts +29 -0
- package/dist/src/commands/author/init.action.d.ts.map +1 -0
- package/dist/src/commands/author/init.action.js +131 -0
- package/dist/src/commands/author/init.action.js.map +1 -0
- package/dist/src/commands/author/init.d.ts +0 -14
- package/dist/src/commands/author/init.d.ts.map +1 -1
- package/dist/src/commands/author/init.js +3 -87
- package/dist/src/commands/author/init.js.map +1 -1
- package/dist/src/commands/author/mcp-init.d.ts +1 -0
- package/dist/src/commands/author/mcp-init.d.ts.map +1 -1
- package/dist/src/commands/author/mcp-init.js +21 -13
- package/dist/src/commands/author/mcp-init.js.map +1 -1
- package/dist/src/commands/author/subagent.d.ts +1 -0
- package/dist/src/commands/author/subagent.d.ts.map +1 -1
- package/dist/src/commands/author/subagent.js +23 -15
- package/dist/src/commands/author/subagent.js.map +1 -1
- package/dist/src/commands/author/transform.d.ts +1 -0
- package/dist/src/commands/author/transform.d.ts.map +1 -1
- package/dist/src/commands/author/transform.js +23 -15
- package/dist/src/commands/author/transform.js.map +1 -1
- package/dist/src/commands/config.d.ts +2 -0
- package/dist/src/commands/config.d.ts.map +1 -1
- package/dist/src/commands/config.js +43 -28
- package/dist/src/commands/config.js.map +1 -1
- package/dist/src/commands/create.d.ts +1 -0
- package/dist/src/commands/create.d.ts.map +1 -1
- package/dist/src/commands/create.js +28 -19
- package/dist/src/commands/create.js.map +1 -1
- package/dist/src/commands/diff.d.ts +4 -0
- package/dist/src/commands/diff.d.ts.map +1 -1
- package/dist/src/commands/diff.js +57 -42
- package/dist/src/commands/diff.js.map +1 -1
- package/dist/src/commands/diff.test.js +30 -0
- package/dist/src/commands/diff.test.js.map +1 -1
- package/dist/src/commands/import-local.d.ts +7 -0
- package/dist/src/commands/import-local.d.ts.map +1 -1
- package/dist/src/commands/import-local.js +43 -34
- package/dist/src/commands/import-local.js.map +1 -1
- package/dist/src/commands/import.d.ts +6 -0
- package/dist/src/commands/import.d.ts.map +1 -1
- package/dist/src/commands/import.js +23 -14
- package/dist/src/commands/import.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/info.d.ts +7 -0
- package/dist/src/commands/info.d.ts.map +1 -1
- package/dist/src/commands/info.js +77 -68
- package/dist/src/commands/info.js.map +1 -1
- package/dist/src/commands/install-skill.d.ts +3 -0
- package/dist/src/commands/install-skill.d.ts.map +1 -1
- package/dist/src/commands/install-skill.js +23 -15
- package/dist/src/commands/install-skill.js.map +1 -1
- package/dist/src/commands/install.d.ts +21 -0
- package/dist/src/commands/install.d.ts.map +1 -1
- package/dist/src/commands/install.js +154 -139
- package/dist/src/commands/install.js.map +1 -1
- package/dist/src/commands/login.d.ts +4 -0
- package/dist/src/commands/login.d.ts.map +1 -1
- package/dist/src/commands/login.js +56 -47
- package/dist/src/commands/login.js.map +1 -1
- package/dist/src/commands/logout.d.ts +1 -0
- package/dist/src/commands/logout.d.ts.map +1 -1
- package/dist/src/commands/logout.js +36 -27
- package/dist/src/commands/logout.js.map +1 -1
- package/dist/src/commands/manage.d.ts +3 -9
- package/dist/src/commands/manage.d.ts.map +1 -1
- package/dist/src/commands/manage.js +69 -45
- package/dist/src/commands/manage.js.map +1 -1
- package/dist/src/commands/merge.d.ts +7 -0
- package/dist/src/commands/merge.d.ts.map +1 -1
- package/dist/src/commands/merge.js +117 -108
- package/dist/src/commands/merge.js.map +1 -1
- package/dist/src/commands/pin.d.ts +2 -0
- package/dist/src/commands/pin.d.ts.map +1 -1
- package/dist/src/commands/pin.js +88 -73
- package/dist/src/commands/pin.js.map +1 -1
- package/dist/src/commands/recommend.d.ts +1 -0
- package/dist/src/commands/recommend.d.ts.map +1 -1
- package/dist/src/commands/recommend.js +35 -27
- package/dist/src/commands/recommend.js.map +1 -1
- package/dist/src/commands/search-formatters.d.ts +1 -0
- package/dist/src/commands/search-formatters.d.ts.map +1 -1
- package/dist/src/commands/search-formatters.js +3 -0
- package/dist/src/commands/search-formatters.js.map +1 -1
- package/dist/src/commands/search.action.d.ts +16 -0
- package/dist/src/commands/search.action.d.ts.map +1 -0
- package/dist/src/commands/search.action.js +384 -0
- package/dist/src/commands/search.action.js.map +1 -0
- package/dist/src/commands/search.d.ts +3 -0
- package/dist/src/commands/search.d.ts.map +1 -1
- package/dist/src/commands/search.js +5 -343
- package/dist/src/commands/search.js.map +1 -1
- package/dist/src/commands/sync.action.d.ts +39 -0
- package/dist/src/commands/sync.action.d.ts.map +1 -0
- package/dist/src/commands/sync.action.js +353 -0
- package/dist/src/commands/sync.action.js.map +1 -0
- package/dist/src/commands/sync.d.ts +3 -0
- package/dist/src/commands/sync.d.ts.map +1 -1
- package/dist/src/commands/sync.js +8 -310
- package/dist/src/commands/sync.js.map +1 -1
- package/dist/src/commands/telemetry.action.d.ts +38 -0
- package/dist/src/commands/telemetry.action.d.ts.map +1 -0
- package/dist/src/commands/telemetry.action.js +350 -0
- package/dist/src/commands/telemetry.action.js.map +1 -0
- package/dist/src/commands/telemetry.d.ts +30 -0
- package/dist/src/commands/telemetry.d.ts.map +1 -0
- package/dist/src/commands/telemetry.helpers.d.ts +58 -0
- package/dist/src/commands/telemetry.helpers.d.ts.map +1 -0
- package/dist/src/commands/telemetry.helpers.js +173 -0
- package/dist/src/commands/telemetry.helpers.js.map +1 -0
- package/dist/src/commands/telemetry.helpers.test.d.ts +15 -0
- package/dist/src/commands/telemetry.helpers.test.d.ts.map +1 -0
- package/dist/src/commands/telemetry.helpers.test.js +240 -0
- package/dist/src/commands/telemetry.helpers.test.js.map +1 -0
- package/dist/src/commands/telemetry.js +65 -0
- package/dist/src/commands/telemetry.js.map +1 -0
- package/dist/src/commands/telemetry.test.d.ts +18 -0
- package/dist/src/commands/telemetry.test.d.ts.map +1 -0
- package/dist/src/commands/telemetry.test.js +401 -0
- package/dist/src/commands/telemetry.test.js.map +1 -0
- package/dist/src/commands/whoami.d.ts +1 -0
- package/dist/src/commands/whoami.d.ts.map +1 -1
- package/dist/src/commands/whoami.js +29 -21
- package/dist/src/commands/whoami.js.map +1 -1
- package/dist/src/index.js +3 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/utils/manifest.d.ts +75 -0
- package/dist/src/utils/manifest.d.ts.map +1 -1
- package/dist/src/utils/manifest.js +78 -0
- package/dist/src/utils/manifest.js.map +1 -1
- package/dist/src/utils/manifest.test.d.ts +20 -0
- package/dist/src/utils/manifest.test.d.ts.map +1 -0
- package/dist/src/utils/manifest.test.js +344 -0
- package/dist/src/utils/manifest.test.js.map +1 -0
- package/dist/src/utils/open-database.d.ts +10 -2
- package/dist/src/utils/open-database.d.ts.map +1 -1
- package/dist/src/utils/open-database.js +15 -2
- package/dist/src/utils/open-database.js.map +1 -1
- package/dist/src/utils/skills-directory.d.ts.map +1 -1
- package/dist/src/utils/skills-directory.js +5 -1
- package/dist/src/utils/skills-directory.js.map +1 -1
- package/dist/tests/e2e/audit-sources-apply.test.d.ts +13 -0
- package/dist/tests/e2e/audit-sources-apply.test.d.ts.map +1 -0
- package/dist/tests/e2e/audit-sources-apply.test.js +166 -0
- package/dist/tests/e2e/audit-sources-apply.test.js.map +1 -0
- package/dist/tests/e2e/audit-sources-recovery.test.d.ts +15 -0
- package/dist/tests/e2e/audit-sources-recovery.test.d.ts.map +1 -0
- package/dist/tests/e2e/audit-sources-recovery.test.js +179 -0
- package/dist/tests/e2e/audit-sources-recovery.test.js.map +1 -0
- package/dist/tests/e2e/audit-sources-roundtrip.test.d.ts +23 -0
- package/dist/tests/e2e/audit-sources-roundtrip.test.d.ts.map +1 -0
- package/dist/tests/e2e/audit-sources-roundtrip.test.js +107 -0
- package/dist/tests/e2e/audit-sources-roundtrip.test.js.map +1 -0
- package/dist/tests/e2e/utils/source-recovery-fixture.d.ts +49 -0
- package/dist/tests/e2e/utils/source-recovery-fixture.d.ts.map +1 -0
- package/dist/tests/e2e/utils/source-recovery-fixture.js +106 -0
- package/dist/tests/e2e/utils/source-recovery-fixture.js.map +1 -0
- package/dist/tests/embedding-probe-stdio.test.d.ts +11 -0
- package/dist/tests/embedding-probe-stdio.test.d.ts.map +1 -0
- package/dist/tests/embedding-probe-stdio.test.js +58 -0
- package/dist/tests/embedding-probe-stdio.test.js.map +1 -0
- package/dist/tests/init.test.js +2 -1
- package/dist/tests/init.test.js.map +1 -1
- package/dist/tests/install-quarantine.test.d.ts +10 -0
- package/dist/tests/install-quarantine.test.d.ts.map +1 -0
- package/dist/tests/install-quarantine.test.js +86 -0
- package/dist/tests/install-quarantine.test.js.map +1 -0
- package/package.json +5 -5
- package/templates/skill-telemetry.cmd +16 -0
- package/templates/skill-telemetry.sh +199 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Tests for telemetry.helpers.ts — atomic settings.json merger.
|
|
3
|
+
* @module @skillsmith/cli/commands/telemetry.helpers.test
|
|
4
|
+
* @see SMI-5021 Wave 3 Step 2 — plan line 717
|
|
5
|
+
*
|
|
6
|
+
* Covers:
|
|
7
|
+
* - addSkillHookEntries: empty settings → well-formed hooks block
|
|
8
|
+
* - addSkillHookEntries: idempotent (second add is a no-op)
|
|
9
|
+
* - addSkillHookEntries: throws on foreign Skill matcher command path
|
|
10
|
+
* - removeSkillHookEntries: removes only Skillsmith entries
|
|
11
|
+
* - removeSkillHookEntries: on empty settings → no-op
|
|
12
|
+
* - writeClaudeSettings: atomic temp-file → rename correctness
|
|
13
|
+
*/
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=telemetry.helpers.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.helpers.test.d.ts","sourceRoot":"","sources":["../../../src/commands/telemetry.helpers.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG"}
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Tests for telemetry.helpers.ts — atomic settings.json merger.
|
|
3
|
+
* @module @skillsmith/cli/commands/telemetry.helpers.test
|
|
4
|
+
* @see SMI-5021 Wave 3 Step 2 — plan line 717
|
|
5
|
+
*
|
|
6
|
+
* Covers:
|
|
7
|
+
* - addSkillHookEntries: empty settings → well-formed hooks block
|
|
8
|
+
* - addSkillHookEntries: idempotent (second add is a no-op)
|
|
9
|
+
* - addSkillHookEntries: throws on foreign Skill matcher command path
|
|
10
|
+
* - removeSkillHookEntries: removes only Skillsmith entries
|
|
11
|
+
* - removeSkillHookEntries: on empty settings → no-op
|
|
12
|
+
* - writeClaudeSettings: atomic temp-file → rename correctness
|
|
13
|
+
*/
|
|
14
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
// fs mock — intercepts node:fs (used by telemetry.helpers.ts)
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
const memfs = {};
|
|
19
|
+
let existsResult = false;
|
|
20
|
+
vi.mock('node:fs', () => ({
|
|
21
|
+
existsSync: vi.fn((_p) => existsResult),
|
|
22
|
+
readFileSync: vi.fn((path) => {
|
|
23
|
+
const content = memfs[path];
|
|
24
|
+
if (content === undefined)
|
|
25
|
+
throw Object.assign(new Error(`ENOENT: ${path}`), { code: 'ENOENT' });
|
|
26
|
+
return content;
|
|
27
|
+
}),
|
|
28
|
+
writeFileSync: vi.fn((path, content) => {
|
|
29
|
+
memfs[path] = content;
|
|
30
|
+
}),
|
|
31
|
+
renameSync: vi.fn((src, dst) => {
|
|
32
|
+
const content = memfs[src];
|
|
33
|
+
if (content === undefined)
|
|
34
|
+
throw new Error(`ENOENT: ${src}`);
|
|
35
|
+
memfs[dst] = content;
|
|
36
|
+
delete memfs[src];
|
|
37
|
+
}),
|
|
38
|
+
mkdirSync: vi.fn(() => undefined),
|
|
39
|
+
chmodSync: vi.fn(() => undefined),
|
|
40
|
+
}));
|
|
41
|
+
import { loadClaudeSettings, addSkillHookEntries, removeSkillHookEntries, writeClaudeSettings, TelemetryHookError, } from './telemetry.helpers.js';
|
|
42
|
+
// ---------------------------------------------------------------------------
|
|
43
|
+
// Helpers
|
|
44
|
+
// ---------------------------------------------------------------------------
|
|
45
|
+
const HOOK_PATH = '/home/test/.skillsmith/hooks/skill-telemetry.sh';
|
|
46
|
+
function emptySettings() {
|
|
47
|
+
return {};
|
|
48
|
+
}
|
|
49
|
+
function settingsWithSkillsmithHooks() {
|
|
50
|
+
return {
|
|
51
|
+
hooks: {
|
|
52
|
+
PreToolUse: [
|
|
53
|
+
{
|
|
54
|
+
matcher: 'Skill',
|
|
55
|
+
hooks: [{ type: 'command', command: `${HOOK_PATH} pre` }],
|
|
56
|
+
},
|
|
57
|
+
],
|
|
58
|
+
PostToolUse: [
|
|
59
|
+
{
|
|
60
|
+
matcher: 'Skill',
|
|
61
|
+
hooks: [{ type: 'command', command: `${HOOK_PATH} post` }],
|
|
62
|
+
},
|
|
63
|
+
],
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function settingsWithForeignSkillHook() {
|
|
68
|
+
return {
|
|
69
|
+
hooks: {
|
|
70
|
+
PreToolUse: [
|
|
71
|
+
{
|
|
72
|
+
matcher: 'Skill',
|
|
73
|
+
hooks: [{ type: 'command', command: '/other/tool/skill-hook.sh pre' }],
|
|
74
|
+
},
|
|
75
|
+
],
|
|
76
|
+
PostToolUse: [],
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
// ---------------------------------------------------------------------------
|
|
81
|
+
// Setup / teardown
|
|
82
|
+
// ---------------------------------------------------------------------------
|
|
83
|
+
beforeEach(() => {
|
|
84
|
+
for (const k of Object.keys(memfs))
|
|
85
|
+
delete memfs[k];
|
|
86
|
+
existsResult = false;
|
|
87
|
+
vi.clearAllMocks();
|
|
88
|
+
});
|
|
89
|
+
afterEach(() => {
|
|
90
|
+
for (const k of Object.keys(memfs))
|
|
91
|
+
delete memfs[k];
|
|
92
|
+
});
|
|
93
|
+
// ---------------------------------------------------------------------------
|
|
94
|
+
// loadClaudeSettings
|
|
95
|
+
// ---------------------------------------------------------------------------
|
|
96
|
+
describe('loadClaudeSettings', () => {
|
|
97
|
+
it('returns empty object when file does not exist', () => {
|
|
98
|
+
existsResult = false;
|
|
99
|
+
const result = loadClaudeSettings('user');
|
|
100
|
+
expect(result).toEqual({});
|
|
101
|
+
});
|
|
102
|
+
it('returns parsed JSON when file exists and is valid', async () => {
|
|
103
|
+
existsResult = true;
|
|
104
|
+
const { existsSync, readFileSync } = await import('node:fs');
|
|
105
|
+
existsSync.mockReturnValueOnce(true);
|
|
106
|
+
readFileSync.mockReturnValueOnce(JSON.stringify({ hooks: { PreToolUse: [] } }));
|
|
107
|
+
const result = loadClaudeSettings('user');
|
|
108
|
+
expect(result).toHaveProperty('hooks');
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
// ---------------------------------------------------------------------------
|
|
112
|
+
// addSkillHookEntries
|
|
113
|
+
// ---------------------------------------------------------------------------
|
|
114
|
+
describe('addSkillHookEntries', () => {
|
|
115
|
+
it('adds PreToolUse and PostToolUse Skill matchers to empty settings', () => {
|
|
116
|
+
const result = addSkillHookEntries(emptySettings(), HOOK_PATH);
|
|
117
|
+
expect(result.hooks?.PreToolUse).toHaveLength(1);
|
|
118
|
+
expect(result.hooks?.PreToolUse?.[0]?.matcher).toBe('Skill');
|
|
119
|
+
expect(result.hooks?.PreToolUse?.[0]?.hooks?.[0]?.command).toBe(`${HOOK_PATH} pre`);
|
|
120
|
+
expect(result.hooks?.PostToolUse).toHaveLength(1);
|
|
121
|
+
expect(result.hooks?.PostToolUse?.[0]?.matcher).toBe('Skill');
|
|
122
|
+
expect(result.hooks?.PostToolUse?.[0]?.hooks?.[0]?.command).toBe(`${HOOK_PATH} post`);
|
|
123
|
+
});
|
|
124
|
+
it('is idempotent — calling add twice produces only one entry per array', () => {
|
|
125
|
+
const once = addSkillHookEntries(emptySettings(), HOOK_PATH);
|
|
126
|
+
const twice = addSkillHookEntries(once, HOOK_PATH);
|
|
127
|
+
expect(twice.hooks?.PreToolUse).toHaveLength(1);
|
|
128
|
+
expect(twice.hooks?.PostToolUse).toHaveLength(1);
|
|
129
|
+
});
|
|
130
|
+
it('preserves existing non-Skill hook entries alongside new Skill entry', () => {
|
|
131
|
+
const existing = {
|
|
132
|
+
hooks: {
|
|
133
|
+
PreToolUse: [{ matcher: 'Bash', hooks: [{ type: 'command', command: 'echo pre-bash' }] }],
|
|
134
|
+
PostToolUse: [],
|
|
135
|
+
},
|
|
136
|
+
};
|
|
137
|
+
const result = addSkillHookEntries(existing, HOOK_PATH);
|
|
138
|
+
// Should have both Bash and Skill entries
|
|
139
|
+
expect(result.hooks?.PreToolUse).toHaveLength(2);
|
|
140
|
+
expect(result.hooks?.PreToolUse?.some((e) => e.matcher === 'Bash')).toBe(true);
|
|
141
|
+
expect(result.hooks?.PreToolUse?.some((e) => e.matcher === 'Skill')).toBe(true);
|
|
142
|
+
});
|
|
143
|
+
it('throws TelemetryHookError with code hook.foreign_skill_matcher when a foreign Skill hook exists', () => {
|
|
144
|
+
const settings = settingsWithForeignSkillHook();
|
|
145
|
+
expect(() => addSkillHookEntries(settings, HOOK_PATH)).toThrow(TelemetryHookError);
|
|
146
|
+
expect(() => addSkillHookEntries(settings, HOOK_PATH)).toThrow(expect.objectContaining({ code: 'hook.foreign_skill_matcher' }));
|
|
147
|
+
});
|
|
148
|
+
it('error message from foreign Skill matcher includes removal instructions', () => {
|
|
149
|
+
const settings = settingsWithForeignSkillHook();
|
|
150
|
+
let caught;
|
|
151
|
+
try {
|
|
152
|
+
addSkillHookEntries(settings, HOOK_PATH);
|
|
153
|
+
}
|
|
154
|
+
catch (e) {
|
|
155
|
+
caught = e;
|
|
156
|
+
}
|
|
157
|
+
expect(caught).toBeInstanceOf(TelemetryHookError);
|
|
158
|
+
const err = caught;
|
|
159
|
+
expect(err.message).toContain('Remove it manually');
|
|
160
|
+
expect(err.message).toContain('skillsmith telemetry install-hook');
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
// ---------------------------------------------------------------------------
|
|
164
|
+
// removeSkillHookEntries
|
|
165
|
+
// ---------------------------------------------------------------------------
|
|
166
|
+
describe('removeSkillHookEntries', () => {
|
|
167
|
+
it('removes Skillsmith Skill entries from both PreToolUse and PostToolUse', () => {
|
|
168
|
+
const settings = settingsWithSkillsmithHooks();
|
|
169
|
+
const result = removeSkillHookEntries(settings, HOOK_PATH);
|
|
170
|
+
expect(result.hooks?.PreToolUse).toHaveLength(0);
|
|
171
|
+
expect(result.hooks?.PostToolUse).toHaveLength(0);
|
|
172
|
+
});
|
|
173
|
+
it('does not touch foreign hooks when removing Skillsmith entries', () => {
|
|
174
|
+
const settings = {
|
|
175
|
+
hooks: {
|
|
176
|
+
PreToolUse: [
|
|
177
|
+
{ matcher: 'Bash', hooks: [{ type: 'command', command: 'echo bash' }] },
|
|
178
|
+
{ matcher: 'Skill', hooks: [{ type: 'command', command: `${HOOK_PATH} pre` }] },
|
|
179
|
+
],
|
|
180
|
+
PostToolUse: [
|
|
181
|
+
{ matcher: 'Skill', hooks: [{ type: 'command', command: `${HOOK_PATH} post` }] },
|
|
182
|
+
],
|
|
183
|
+
},
|
|
184
|
+
};
|
|
185
|
+
const result = removeSkillHookEntries(settings, HOOK_PATH);
|
|
186
|
+
// Bash hook preserved; Skill hook removed
|
|
187
|
+
expect(result.hooks?.PreToolUse).toHaveLength(1);
|
|
188
|
+
expect(result.hooks?.PreToolUse?.[0]?.matcher).toBe('Bash');
|
|
189
|
+
expect(result.hooks?.PostToolUse).toHaveLength(0);
|
|
190
|
+
});
|
|
191
|
+
it('is a no-op when settings has no hooks key', () => {
|
|
192
|
+
const result = removeSkillHookEntries({}, HOOK_PATH);
|
|
193
|
+
expect(result.hooks).toBeUndefined();
|
|
194
|
+
});
|
|
195
|
+
it('is a no-op when no Skill entries exist to remove', () => {
|
|
196
|
+
const settings = {
|
|
197
|
+
hooks: {
|
|
198
|
+
PreToolUse: [{ matcher: 'Bash', hooks: [{ type: 'command', command: 'echo bash' }] }],
|
|
199
|
+
PostToolUse: [],
|
|
200
|
+
},
|
|
201
|
+
};
|
|
202
|
+
const result = removeSkillHookEntries(settings, HOOK_PATH);
|
|
203
|
+
expect(result.hooks?.PreToolUse).toHaveLength(1);
|
|
204
|
+
expect(result.hooks?.PostToolUse).toHaveLength(0);
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
// ---------------------------------------------------------------------------
|
|
208
|
+
// writeClaudeSettings — atomic write correctness
|
|
209
|
+
// ---------------------------------------------------------------------------
|
|
210
|
+
describe('writeClaudeSettings', () => {
|
|
211
|
+
it('writes the settings to a .tmp file then renames to final path', async () => {
|
|
212
|
+
const { writeFileSync, renameSync } = await import('node:fs');
|
|
213
|
+
const settings = { hooks: { PreToolUse: [] } };
|
|
214
|
+
writeClaudeSettings('user', settings);
|
|
215
|
+
expect(writeFileSync).toHaveBeenCalledWith(expect.stringContaining('.tmp'), expect.stringContaining('"PreToolUse"'), expect.anything());
|
|
216
|
+
expect(renameSync).toHaveBeenCalledWith(expect.stringContaining('.tmp'), expect.stringContaining('settings.json'));
|
|
217
|
+
});
|
|
218
|
+
it('second write fully replaces first without partial state', async () => {
|
|
219
|
+
// Simulate sequential write correctness (mirrors manifest.test.ts pattern)
|
|
220
|
+
const first = { hooks: { PreToolUse: [] } };
|
|
221
|
+
const second = {
|
|
222
|
+
hooks: {
|
|
223
|
+
PreToolUse: [
|
|
224
|
+
{ matcher: 'Skill', hooks: [{ type: 'command', command: `${HOOK_PATH} pre` }] },
|
|
225
|
+
],
|
|
226
|
+
},
|
|
227
|
+
};
|
|
228
|
+
writeClaudeSettings('user', first);
|
|
229
|
+
writeClaudeSettings('user', second);
|
|
230
|
+
// After both writes, memfs should contain the second write's content
|
|
231
|
+
const { resolveSettingsPath } = await import('./telemetry.helpers.js');
|
|
232
|
+
const finalPath = resolveSettingsPath('user');
|
|
233
|
+
const raw = memfs[finalPath];
|
|
234
|
+
expect(raw).toBeDefined();
|
|
235
|
+
const parsed = JSON.parse(raw);
|
|
236
|
+
expect(parsed.hooks?.PreToolUse).toHaveLength(1);
|
|
237
|
+
expect(parsed.hooks?.PreToolUse?.[0]?.matcher).toBe('Skill');
|
|
238
|
+
});
|
|
239
|
+
});
|
|
240
|
+
//# sourceMappingURL=telemetry.helpers.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.helpers.test.js","sourceRoot":"","sources":["../../../src/commands/telemetry.helpers.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview `skillsmith telemetry` command group — opt-in telemetry management.
|
|
3
|
+
* @module @skillsmith/cli/commands/telemetry
|
|
4
|
+
* @see SMI-5021 Wave 3 Step 2 — CLI subcommands for telemetry (plan lines 195–196, 576)
|
|
5
|
+
* @see SMI-5128 batch D — action impls + run* logic moved to telemetry.action.ts
|
|
6
|
+
* (sibling-split convention) so the 6 subcommand handlers are withTelemetry-
|
|
7
|
+
* wrapped without this file exceeding the 500-LOC gate. This file retains the
|
|
8
|
+
* commander factory and re-exports the run* test helpers for back-compat.
|
|
9
|
+
*
|
|
10
|
+
* Subcommands:
|
|
11
|
+
* skillsmith telemetry enable
|
|
12
|
+
* skillsmith telemetry disable
|
|
13
|
+
* skillsmith telemetry status
|
|
14
|
+
* skillsmith telemetry install-hook [--scope user|project] [--endpoint <url>]
|
|
15
|
+
* skillsmith telemetry uninstall-hook [--scope user|project]
|
|
16
|
+
* skillsmith telemetry reset-id
|
|
17
|
+
*
|
|
18
|
+
* Privacy invariants (plan line 719):
|
|
19
|
+
* - anonymousId is NEVER printed in full. Only the last 8 hex chars appear in stdout.
|
|
20
|
+
* - The full SHA-256 hex travels only to the events endpoint in hook payloads.
|
|
21
|
+
*
|
|
22
|
+
* Shared-state coordination (plan line 717):
|
|
23
|
+
* - install-hook reads then writes ~/.claude/settings.json via telemetry.helpers.ts
|
|
24
|
+
* - Refuses on foreign Skill matcher (security gate)
|
|
25
|
+
* - manifest read/write always via loadManifest / saveManifest (atomic rename)
|
|
26
|
+
*/
|
|
27
|
+
import { Command } from 'commander';
|
|
28
|
+
import { telemetryEnableAction, telemetryDisableAction, telemetryStatusAction, telemetryInstallHookAction, telemetryUninstallHookAction, telemetryResetIdAction, } from './telemetry.action.js';
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
// Command factory
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
export function createTelemetryCommand() {
|
|
33
|
+
const telemetry = new Command('telemetry').description('Manage Skillsmith telemetry preferences and Claude Code hook installation');
|
|
34
|
+
telemetry
|
|
35
|
+
.command('enable')
|
|
36
|
+
.description('Opt in to anonymous skill-invocation telemetry')
|
|
37
|
+
.action(telemetryEnableAction);
|
|
38
|
+
telemetry
|
|
39
|
+
.command('disable')
|
|
40
|
+
.description('Opt out of telemetry (anonymous ID is retained for re-enable continuity)')
|
|
41
|
+
.action(telemetryDisableAction);
|
|
42
|
+
telemetry
|
|
43
|
+
.command('status')
|
|
44
|
+
.description('Show current telemetry state; triggers annual ID rotation if due')
|
|
45
|
+
.action(telemetryStatusAction);
|
|
46
|
+
telemetry
|
|
47
|
+
.command('install-hook')
|
|
48
|
+
.description('Install the Skill telemetry hook into ~/.claude/settings.json')
|
|
49
|
+
.option('--scope <scope>', 'Settings scope: user (~/.claude/settings.json) or project (./.claude/settings.json)', 'user')
|
|
50
|
+
.option('--endpoint <url>', 'Override the telemetry endpoint (default: prod Supabase events)')
|
|
51
|
+
.action(telemetryInstallHookAction);
|
|
52
|
+
telemetry
|
|
53
|
+
.command('uninstall-hook')
|
|
54
|
+
.description('Remove the Skillsmith Skill hook entries from settings.json')
|
|
55
|
+
.option('--scope <scope>', 'Settings scope: user or project', 'user')
|
|
56
|
+
.action(telemetryUninstallHookAction);
|
|
57
|
+
telemetry
|
|
58
|
+
.command('reset-id')
|
|
59
|
+
.description('Immediately rotate the anonymous ID (previous ID kept for 7-day overlap window)')
|
|
60
|
+
.action(telemetryResetIdAction);
|
|
61
|
+
return telemetry;
|
|
62
|
+
}
|
|
63
|
+
// Internal exports for tests — sourced from telemetry.action.ts (SMI-5128 split).
|
|
64
|
+
export { runEnable, runDisable, runStatus, runInstallHook, runUninstallHook, runResetId, idTail, } from './telemetry.action.js';
|
|
65
|
+
//# sourceMappingURL=telemetry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.js","sourceRoot":"","sources":["../../../src/commands/telemetry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAEnC,OAAO,EACL,qBAAqB,EACrB,sBAAsB,EACtB,qBAAqB,EACrB,0BAA0B,EAC1B,4BAA4B,EAC5B,sBAAsB,GACvB,MAAM,uBAAuB,CAAA;AAE9B,8EAA8E;AAC9E,kBAAkB;AAClB,8EAA8E;AAE9E,MAAM,UAAU,sBAAsB;IACpC,MAAM,SAAS,GAAG,IAAI,OAAO,CAAC,WAAW,CAAC,CAAC,WAAW,CACpD,2EAA2E,CAC5E,CAAA;IAED,SAAS;SACN,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,gDAAgD,CAAC;SAC7D,MAAM,CAAC,qBAAqB,CAAC,CAAA;IAEhC,SAAS;SACN,OAAO,CAAC,SAAS,CAAC;SAClB,WAAW,CAAC,0EAA0E,CAAC;SACvF,MAAM,CAAC,sBAAsB,CAAC,CAAA;IAEjC,SAAS;SACN,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,kEAAkE,CAAC;SAC/E,MAAM,CAAC,qBAAqB,CAAC,CAAA;IAEhC,SAAS;SACN,OAAO,CAAC,cAAc,CAAC;SACvB,WAAW,CAAC,+DAA+D,CAAC;SAC5E,MAAM,CACL,iBAAiB,EACjB,qFAAqF,EACrF,MAAM,CACP;SACA,MAAM,CAAC,kBAAkB,EAAE,iEAAiE,CAAC;SAC7F,MAAM,CAAC,0BAA0B,CAAC,CAAA;IAErC,SAAS;SACN,OAAO,CAAC,gBAAgB,CAAC;SACzB,WAAW,CAAC,6DAA6D,CAAC;SAC1E,MAAM,CAAC,iBAAiB,EAAE,iCAAiC,EAAE,MAAM,CAAC;SACpE,MAAM,CAAC,4BAA4B,CAAC,CAAA;IAEvC,SAAS;SACN,OAAO,CAAC,UAAU,CAAC;SACnB,WAAW,CAAC,iFAAiF,CAAC;SAC9F,MAAM,CAAC,sBAAsB,CAAC,CAAA;IAEjC,OAAO,SAAS,CAAA;AAClB,CAAC;AAED,kFAAkF;AAClF,OAAO,EACL,SAAS,EACT,UAAU,EACV,SAAS,EACT,cAAc,EACd,gBAAgB,EAChB,UAAU,EACV,MAAM,GACP,MAAM,uBAAuB,CAAA"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Tests for `skillsmith telemetry` subcommands.
|
|
3
|
+
* @module @skillsmith/cli/commands/telemetry.test
|
|
4
|
+
* @see SMI-5021 Wave 3 Step 2 — plan lines 700, 703, 706
|
|
5
|
+
*
|
|
6
|
+
* Covers:
|
|
7
|
+
* enable: fresh manifest → generates id, sets enabled=true; idempotent on re-run
|
|
8
|
+
* disable: enabled manifest → sets enabled=false; anonymousId preserved
|
|
9
|
+
* status: prints expected shape (ID tail only); detects + triggers rotation when backdated >365d
|
|
10
|
+
* reset-id: rotates unconditionally; new id distinct; previous id populated
|
|
11
|
+
* install-hook (mocked): adds PreToolUse+PostToolUse; idempotent; throws on foreign Skill matcher
|
|
12
|
+
* uninstall-hook: removes only Skillsmith entries; preserves foreign hooks
|
|
13
|
+
* install-hook --scope project: writes to ./.claude/settings.json
|
|
14
|
+
*
|
|
15
|
+
* Privacy invariant: idTail() — last 8 chars only, never full id.
|
|
16
|
+
*/
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=telemetry.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.test.d.ts","sourceRoot":"","sources":["../../../src/commands/telemetry.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG"}
|