@skillsmith/core 0.11.5 → 0.11.6

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 (94) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/README.md +2 -2
  3. package/dist/.tsbuildinfo +1 -1
  4. package/dist/src/api/client.d.ts.map +1 -1
  5. package/dist/src/api/client.js +5 -0
  6. package/dist/src/api/client.js.map +1 -1
  7. package/dist/src/api/client.test.js +39 -0
  8. package/dist/src/api/client.test.js.map +1 -1
  9. package/dist/src/compatibility/slugs.d.ts +7 -3
  10. package/dist/src/compatibility/slugs.d.ts.map +1 -1
  11. package/dist/src/compatibility/slugs.js +11 -4
  12. package/dist/src/compatibility/slugs.js.map +1 -1
  13. package/dist/src/db/drivers/sqljsDriver.d.ts +8 -0
  14. package/dist/src/db/drivers/sqljsDriver.d.ts.map +1 -1
  15. package/dist/src/db/drivers/sqljsDriver.js +24 -2
  16. package/dist/src/db/drivers/sqljsDriver.js.map +1 -1
  17. package/dist/src/db/migration-runner.d.ts.map +1 -1
  18. package/dist/src/db/migration-runner.js +23 -2
  19. package/dist/src/db/migration-runner.js.map +1 -1
  20. package/dist/src/db/schema.d.ts.map +1 -1
  21. package/dist/src/db/schema.js +29 -3
  22. package/dist/src/db/schema.js.map +1 -1
  23. package/dist/src/exports/services.d.ts +1 -0
  24. package/dist/src/exports/services.d.ts.map +1 -1
  25. package/dist/src/exports/services.js +5 -0
  26. package/dist/src/exports/services.js.map +1 -1
  27. package/dist/src/index.d.ts +1 -1
  28. package/dist/src/index.js +1 -1
  29. package/dist/src/install/index.d.ts +2 -2
  30. package/dist/src/install/index.d.ts.map +1 -1
  31. package/dist/src/install/index.js +1 -1
  32. package/dist/src/install/index.js.map +1 -1
  33. package/dist/src/install/paths.d.ts +155 -1
  34. package/dist/src/install/paths.d.ts.map +1 -1
  35. package/dist/src/install/paths.js +235 -1
  36. package/dist/src/install/paths.js.map +1 -1
  37. package/dist/src/install/paths.test.js +174 -2
  38. package/dist/src/install/paths.test.js.map +1 -1
  39. package/dist/src/services/context-words.d.ts +40 -0
  40. package/dist/src/services/context-words.d.ts.map +1 -0
  41. package/dist/src/services/context-words.js +178 -0
  42. package/dist/src/services/context-words.js.map +1 -0
  43. package/dist/src/services/context-words.test.d.ts +2 -0
  44. package/dist/src/services/context-words.test.d.ts.map +1 -0
  45. package/dist/src/services/context-words.test.js +94 -0
  46. package/dist/src/services/context-words.test.js.map +1 -0
  47. package/dist/src/services/skill-installation.content.d.ts +8 -0
  48. package/dist/src/services/skill-installation.content.d.ts.map +1 -1
  49. package/dist/src/services/skill-installation.content.js +2 -2
  50. package/dist/src/services/skill-installation.content.js.map +1 -1
  51. package/dist/src/services/skill-installation.helpers.d.ts.map +1 -1
  52. package/dist/src/services/skill-installation.helpers.js +24 -2
  53. package/dist/src/services/skill-installation.helpers.js.map +1 -1
  54. package/dist/src/services/skill-installation.helpers.test.js +76 -2
  55. package/dist/src/services/skill-installation.helpers.test.js.map +1 -1
  56. package/dist/src/services/skill-installation.io.d.ts +22 -1
  57. package/dist/src/services/skill-installation.io.d.ts.map +1 -1
  58. package/dist/src/services/skill-installation.io.js +36 -5
  59. package/dist/src/services/skill-installation.io.js.map +1 -1
  60. package/dist/src/services/skill-installation.service.d.ts +2 -0
  61. package/dist/src/services/skill-installation.service.d.ts.map +1 -1
  62. package/dist/src/services/skill-installation.service.js +4 -1
  63. package/dist/src/services/skill-installation.service.js.map +1 -1
  64. package/dist/src/services/skill-manifest.d.ts +21 -0
  65. package/dist/src/services/skill-manifest.d.ts.map +1 -1
  66. package/dist/src/services/skill-manifest.js +51 -6
  67. package/dist/src/services/skill-manifest.js.map +1 -1
  68. package/dist/src/services/skill-manifest.test.d.ts +2 -0
  69. package/dist/src/services/skill-manifest.test.d.ts.map +1 -0
  70. package/dist/src/services/skill-manifest.test.js +202 -0
  71. package/dist/src/services/skill-manifest.test.js.map +1 -0
  72. package/dist/src/types/skill.d.ts +10 -0
  73. package/dist/src/types/skill.d.ts.map +1 -1
  74. package/dist/src/types.d.ts +9 -5
  75. package/dist/src/types.d.ts.map +1 -1
  76. package/dist/tests/db/migration-runner-race.test.d.ts +2 -0
  77. package/dist/tests/db/migration-runner-race.test.d.ts.map +1 -0
  78. package/dist/tests/db/migration-runner-race.test.js +75 -0
  79. package/dist/tests/db/migration-runner-race.test.js.map +1 -0
  80. package/dist/tests/db/schema-async.test.js +37 -1
  81. package/dist/tests/db/schema-async.test.js.map +1 -1
  82. package/dist/tests/db/sqljsDriver.test.js +63 -1
  83. package/dist/tests/db/sqljsDriver.test.js.map +1 -1
  84. package/dist/tests/schema.test.js +43 -1
  85. package/dist/tests/schema.test.js.map +1 -1
  86. package/dist/tests/unit/services/skill-installation.io.client-agent-path.test.d.ts +34 -0
  87. package/dist/tests/unit/services/skill-installation.io.client-agent-path.test.d.ts.map +1 -0
  88. package/dist/tests/unit/services/skill-installation.io.client-agent-path.test.js +246 -0
  89. package/dist/tests/unit/services/skill-installation.io.client-agent-path.test.js.map +1 -0
  90. package/dist/tests/unit/services/skill-installation.service.companion-basedir.test.d.ts +17 -0
  91. package/dist/tests/unit/services/skill-installation.service.companion-basedir.test.d.ts.map +1 -0
  92. package/dist/tests/unit/services/skill-installation.service.companion-basedir.test.js +112 -0
  93. package/dist/tests/unit/services/skill-installation.service.companion-basedir.test.js.map +1 -0
  94. package/package.json +1 -1
@@ -5,8 +5,29 @@
5
5
  * and isSqlJsAvailable. The better-sqlite3 mock is scoped with vi.isolateModules()
6
6
  * to prevent contaminating betterSqlite3Driver.test.ts.
7
7
  */
8
- import { describe, it, expect, afterEach } from 'vitest';
8
+ import { describe, it, expect, afterEach, beforeEach, vi } from 'vitest';
9
+ import { existsSync, readFileSync, mkdtempSync, rmSync } from 'node:fs';
10
+ import { tmpdir } from 'node:os';
11
+ import { join } from 'node:path';
9
12
  import { createSqlJsDatabase, SqlJsDatabaseAdapter, isSqlJsAvailable, } from '../../src/db/drivers/sqljsDriver.js';
13
+ // SMI-5997: sqljsDriver.ts imports writeFileSync from 'node:fs' as a live ESM
14
+ // binding, which vi.spyOn cannot redefine ("Module namespace is not
15
+ // configurable in ESM"). vi.mock + importOriginal is the supported way to
16
+ // intercept a single named export while passing everything else through.
17
+ const failNextWrite = vi.hoisted(() => ({ value: false }));
18
+ vi.mock('node:fs', async (importOriginal) => {
19
+ const actual = await importOriginal();
20
+ return {
21
+ ...actual,
22
+ writeFileSync: (...args) => {
23
+ if (failNextWrite.value) {
24
+ failNextWrite.value = false;
25
+ throw new Error('simulated crash mid-write');
26
+ }
27
+ return actual.writeFileSync(...args);
28
+ },
29
+ };
30
+ });
10
31
  describe('sqljsDriver — edge cases', () => {
11
32
  describe('isSqlJsAvailable', () => {
12
33
  it('returns true when fts5-sql-bundle is resolvable', () => {
@@ -71,5 +92,46 @@ describe('sqljsDriver — edge cases', () => {
71
92
  await expect(createSqlJsDatabase(nonExistentPath, { fileMustExist: true })).rejects.toThrow(/SQLITE_CANTOPEN/);
72
93
  });
73
94
  });
95
+ describe('persist() — atomic write (SMI-5997)', () => {
96
+ let dir;
97
+ let dbPath;
98
+ beforeEach(() => {
99
+ dir = mkdtempSync(join(tmpdir(), 'sqljs-persist-'));
100
+ dbPath = join(dir, 'test.db');
101
+ });
102
+ afterEach(() => {
103
+ failNextWrite.value = false;
104
+ rmSync(dir, { recursive: true, force: true });
105
+ });
106
+ it('writes via temp file + rename, leaving no leftover .tmp file', async () => {
107
+ const db = await createSqlJsDatabase(dbPath);
108
+ db.exec('CREATE TABLE t (id INTEGER PRIMARY KEY, name TEXT)');
109
+ db.exec("INSERT INTO t (name) VALUES ('alpha')");
110
+ db.persist();
111
+ expect(existsSync(dbPath)).toBe(true);
112
+ expect(existsSync(`${dbPath}.tmp`)).toBe(false);
113
+ expect(readFileSync(dbPath).length).toBeGreaterThan(0);
114
+ db.close();
115
+ });
116
+ it('leaves the original file byte-for-byte untouched if the write is interrupted', async () => {
117
+ const db = await createSqlJsDatabase(dbPath);
118
+ db.exec('CREATE TABLE t (id INTEGER PRIMARY KEY, name TEXT)');
119
+ db.exec("INSERT INTO t (name) VALUES ('alpha')");
120
+ db.persist();
121
+ const originalContent = readFileSync(dbPath);
122
+ expect(originalContent.length).toBeGreaterThan(0);
123
+ db.exec("INSERT INTO t (name) VALUES ('beta')");
124
+ // Simulate a crash/kill mid-write: writeFileSync (to the temp file)
125
+ // throws before rename() ever runs.
126
+ failNextWrite.value = true;
127
+ expect(() => db.persist()).toThrow('simulated crash mid-write');
128
+ // Reproduces the SMI-5997 incident check in reverse: the real file
129
+ // must never be truncated by a failed write, only ever replaced
130
+ // wholesale by a successful rename().
131
+ expect(readFileSync(dbPath)).toEqual(originalContent);
132
+ expect(existsSync(`${dbPath}.tmp`)).toBe(false);
133
+ db.close();
134
+ });
135
+ });
74
136
  });
75
137
  //# sourceMappingURL=sqljsDriver.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sqljsDriver.test.js","sourceRoot":"","sources":["../../../tests/db/sqljsDriver.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sqljsDriver.test.js","sourceRoot":"","sources":["../../../tests/db/sqljsDriver.test.ts"],"names":[],"mappings":"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"}
@@ -2,7 +2,11 @@
2
2
  * SMI-577: Database Schema Tests
3
3
  */
4
4
  import { describe, it, expect, beforeEach, afterEach } from 'vitest';
5
- import { createDatabase, closeDatabase, getSchemaVersion, runMigrations, SCHEMA_VERSION, } from '../src/db/schema.js';
5
+ import { mkdtempSync, rmSync, writeFileSync } from 'node:fs';
6
+ import { tmpdir } from 'node:os';
7
+ import { join } from 'node:path';
8
+ import { createDatabase, openDatabase, closeDatabase, getSchemaVersion, runMigrations, SCHEMA_VERSION, } from '../src/db/schema.js';
9
+ import { isBetterSqlite3Available } from '../src/db/drivers/betterSqlite3Driver.js';
6
10
  describe('Database Schema', () => {
7
11
  let db;
8
12
  beforeEach(() => {
@@ -163,6 +167,44 @@ describe('Database Schema', () => {
163
167
  expect(indexNames).toContain('idx_skills_quality_score');
164
168
  });
165
169
  });
170
+ describe('openDatabase — empty/corrupt database detection (SMI-5997)', () => {
171
+ let dir;
172
+ beforeEach(() => {
173
+ dir = mkdtempSync(join(tmpdir(), 'schema-open-sync-'));
174
+ });
175
+ afterEach(() => {
176
+ rmSync(dir, { recursive: true, force: true });
177
+ });
178
+ it('throws an actionable error for a 0-byte file (no tables, no schema_version)', () => {
179
+ if (!isBetterSqlite3Available()) {
180
+ console.log('Skipping test: no SQLite driver available');
181
+ return;
182
+ }
183
+ const testPath = join(dir, 'empty-corrupt.db');
184
+ // Reproduces the SMI-5997 incident via the deprecated sync path
185
+ // (packages/cli/src/commands/merge.ts still calls openDatabase()
186
+ // directly) — SQLite treats a 0-byte file as a valid, openable, empty
187
+ // database, so this must be caught by the zero-table check rather
188
+ // than a native SQLITE_CANTOPEN/corruption error.
189
+ writeFileSync(testPath, Buffer.alloc(0));
190
+ expect(() => openDatabase(testPath)).toThrow(/empty or corrupt/);
191
+ });
192
+ it('still treats a file with real tables but no schema_version as a legacy import', () => {
193
+ if (!isBetterSqlite3Available()) {
194
+ console.log('Skipping test: no SQLite driver available');
195
+ return;
196
+ }
197
+ const testPath = join(dir, 'legacy-import.db');
198
+ const seedDb = createDatabase(testPath);
199
+ seedDb.exec('DROP TABLE schema_version');
200
+ closeDatabase(seedDb);
201
+ const reopened = openDatabase(testPath);
202
+ expect(reopened.open).toBe(true);
203
+ const version = getSchemaVersion(reopened);
204
+ expect(version).toBe(SCHEMA_VERSION);
205
+ closeDatabase(reopened);
206
+ });
207
+ });
166
208
  describe('closeDatabase (SMI-4640)', () => {
167
209
  it('tolerates undefined without throwing', () => {
168
210
  expect(() => closeDatabase(undefined)).not.toThrow();
@@ -1 +1 @@
1
- {"version":3,"file":"schema.test.js","sourceRoot":"","sources":["../../tests/schema.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"schema.test.js","sourceRoot":"","sources":["../../tests/schema.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * SMI-5980 (Wave 3): writeInstallFiles must route the companion-subagent
3
+ * write through COMPANION_AGENT_TARGETS (install/paths.ts) for the caller's
4
+ * `client`, not a hardcoded `path.join(os.homedir(), '.claude', 'agents')`
5
+ * literal.
6
+ *
7
+ * `homedir()` is mocked to a controlled tmp directory BEFORE `paths.ts` is
8
+ * first imported — COMPANION_AGENT_TARGETS is a module-level constant
9
+ * computed once at import time from `homedir()`, so every assertion below
10
+ * compares against that SAME already-resolved map rather than a second,
11
+ * independently-hardcoded expectation. This also keeps the test from ever
12
+ * writing to a real developer/CI machine's actual home directory.
13
+ *
14
+ * SMI-5982 (Wave 6): antigravity's `COMPANION_AGENT_TARGETS` entry uses a
15
+ * RELATIVE `dir` (resolved against `process.cwd()`, not `homedir()`) — its
16
+ * own dedicated describe block below chdir's into an isolated tmp directory
17
+ * per test (never TEST_HOME, never the real repo checkout) rather than
18
+ * relying on the homedir() mock every other client's assertions use.
19
+ *
20
+ * SMI-5982 code-review fix #1 (BLOCKING, cwd-dependent resolution):
21
+ * `writeInstallFiles()` now resolves antigravity's relative `dir` via
22
+ * `resolveCompanionAgentPath()`'s explicit `baseDir` param (defaulting to
23
+ * `process.cwd()` at the call site, not deferred to whatever `fs` call
24
+ * eventually consumes the path) — so `result.subagentPath` is now an
25
+ * ABSOLUTE path even for antigravity, not the raw relative string. The
26
+ * `it.each` below covers both the omitted-`companionBaseDir` (falls back to
27
+ * `process.cwd()`, which this describe block's chdir controls) and an
28
+ * explicit `companionBaseDir` override.
29
+ *
30
+ * Split out of skill-installation.io.test.ts to stay under the 500-line
31
+ * CI gate (same rationale as skill-installation.io.symlink.test.ts).
32
+ */
33
+ export {};
34
+ //# sourceMappingURL=skill-installation.io.client-agent-path.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-installation.io.client-agent-path.test.d.ts","sourceRoot":"","sources":["../../../../tests/unit/services/skill-installation.io.client-agent-path.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG"}
@@ -0,0 +1,246 @@
1
+ /**
2
+ * SMI-5980 (Wave 3): writeInstallFiles must route the companion-subagent
3
+ * write through COMPANION_AGENT_TARGETS (install/paths.ts) for the caller's
4
+ * `client`, not a hardcoded `path.join(os.homedir(), '.claude', 'agents')`
5
+ * literal.
6
+ *
7
+ * `homedir()` is mocked to a controlled tmp directory BEFORE `paths.ts` is
8
+ * first imported — COMPANION_AGENT_TARGETS is a module-level constant
9
+ * computed once at import time from `homedir()`, so every assertion below
10
+ * compares against that SAME already-resolved map rather than a second,
11
+ * independently-hardcoded expectation. This also keeps the test from ever
12
+ * writing to a real developer/CI machine's actual home directory.
13
+ *
14
+ * SMI-5982 (Wave 6): antigravity's `COMPANION_AGENT_TARGETS` entry uses a
15
+ * RELATIVE `dir` (resolved against `process.cwd()`, not `homedir()`) — its
16
+ * own dedicated describe block below chdir's into an isolated tmp directory
17
+ * per test (never TEST_HOME, never the real repo checkout) rather than
18
+ * relying on the homedir() mock every other client's assertions use.
19
+ *
20
+ * SMI-5982 code-review fix #1 (BLOCKING, cwd-dependent resolution):
21
+ * `writeInstallFiles()` now resolves antigravity's relative `dir` via
22
+ * `resolveCompanionAgentPath()`'s explicit `baseDir` param (defaulting to
23
+ * `process.cwd()` at the call site, not deferred to whatever `fs` call
24
+ * eventually consumes the path) — so `result.subagentPath` is now an
25
+ * ABSOLUTE path even for antigravity, not the raw relative string. The
26
+ * `it.each` below covers both the omitted-`companionBaseDir` (falls back to
27
+ * `process.cwd()`, which this describe block's chdir controls) and an
28
+ * explicit `companionBaseDir` override.
29
+ *
30
+ * Split out of skill-installation.io.test.ts to stay under the 500-line
31
+ * CI gate (same rationale as skill-installation.io.symlink.test.ts).
32
+ */
33
+ import { afterAll, afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
34
+ import * as fs from 'fs/promises';
35
+ import * as path from 'path';
36
+ import * as os from 'node:os';
37
+ const { TEST_HOME, homedirMock } = vi.hoisted(() => {
38
+ const home = '/tmp/skillsmith-wif-client-agent-path-test-' + process.pid;
39
+ return { TEST_HOME: home, homedirMock: vi.fn(() => home) };
40
+ });
41
+ vi.mock('node:os', async (importOriginal) => {
42
+ const actual = await importOriginal();
43
+ return { ...actual, homedir: homedirMock };
44
+ });
45
+ import { writeInstallFiles } from '../../../src/services/skill-installation.io.js';
46
+ import { CLIENT_IDS, COMPANION_AGENT_TARGETS } from '../../../src/install/paths.js';
47
+ afterAll(async () => {
48
+ await fs.rm(TEST_HOME, { recursive: true, force: true }).catch(() => { });
49
+ });
50
+ /**
51
+ * Fresh skillsDir/installPath per test so parallel `it.each` iterations
52
+ * (all sharing TEST_HOME) never collide with each other.
53
+ */
54
+ async function freshInstallPath(label) {
55
+ const skillsDir = path.join(TEST_HOME, 'src', label, 'skills');
56
+ await fs.mkdir(skillsDir, { recursive: true });
57
+ return { skillsDir, installPath: path.join(skillsDir, 'my-skill') };
58
+ }
59
+ describe('writeInstallFiles companion-subagent path per client (SMI-5980 regression)', () => {
60
+ beforeEach(() => {
61
+ homedirMock.mockReturnValue(TEST_HOME);
62
+ });
63
+ // SMI-5982 (Wave 6): antigravity is excluded from this generic 'flat'
64
+ // it.each — its dir is a RELATIVE path (resolved against process.cwd(),
65
+ // NOT the mocked homedir()), so writing it here would land outside
66
+ // TEST_HOME, pollute the real working tree, and never get cleaned up by
67
+ // this file's afterAll. It gets its own cwd-isolated describe block below.
68
+ it.each(CLIENT_IDS.filter((id) => id !== 'antigravity'))('writes the companion subagent for client=%s at exactly COMPANION_AGENT_TARGETS[client]', async (client) => {
69
+ const { skillsDir, installPath } = await freshInstallPath(client);
70
+ const result = await writeInstallFiles(installPath, skillsDir, 'my-skill', '# hello', [], '---\nname: my-skill-specialist\n---\nbody', client);
71
+ // Every remaining client uses 'flat' mode (copilot's own
72
+ // '{name}.agent.md' pattern, SMI-5980 PR-review finding, included).
73
+ const target = COMPANION_AGENT_TARGETS[client];
74
+ const expectedPath = path.join(target.dir, target.filenamePattern.replace('{name}', 'my-skill'));
75
+ expect(result.subagentPath).toBe(expectedPath);
76
+ expect(await fs.readFile(expectedPath, 'utf8')).toBe('---\nname: my-skill-specialist\n---\nbody');
77
+ });
78
+ it('defaults to the canonical (claude-code) target when client is omitted (regression: unchanged)', async () => {
79
+ const { skillsDir, installPath } = await freshInstallPath('default-client');
80
+ const result = await writeInstallFiles(installPath, skillsDir, 'my-skill', '# hello', [], 'subagent body'
81
+ // client omitted — must resolve exactly like the old hardcoded default.
82
+ );
83
+ const expectedPath = path.join(COMPANION_AGENT_TARGETS['claude-code'].dir, 'my-skill-specialist.md');
84
+ expect(result.subagentPath).toBe(expectedPath);
85
+ expect(await fs.readFile(expectedPath, 'utf8')).toBe('subagent body');
86
+ });
87
+ it('claude-code and cursor land in the SAME directory (both default, no independent evidence for cursor)', async () => {
88
+ const claudeCode = await freshInstallPath('cc-vs-cursor-claude');
89
+ const cursor = await freshInstallPath('cc-vs-cursor-cursor');
90
+ const claudeResult = await writeInstallFiles(claudeCode.installPath, claudeCode.skillsDir, 'my-skill', '# hello', [], 'body', 'claude-code');
91
+ const cursorResult = await writeInstallFiles(cursor.installPath, cursor.skillsDir, 'my-skill', '# hello', [], 'body', 'cursor');
92
+ expect(path.dirname(cursorResult.subagentPath ?? '')).toBe(path.dirname(claudeResult.subagentPath ?? ''));
93
+ });
94
+ it('copilot and opencode land at their own real, literal directories (code-review finding: not just "different from claude-code")', async () => {
95
+ const copilot = await freshInstallPath('copilot-diff');
96
+ const opencode = await freshInstallPath('opencode-diff');
97
+ const copilotResult = await writeInstallFiles(copilot.installPath, copilot.skillsDir, 'my-skill', '# hello', [], 'body', 'copilot');
98
+ const opencodeResult = await writeInstallFiles(opencode.installPath, opencode.skillsDir, 'my-skill', '# hello', [], 'body', 'opencode');
99
+ // Independently-constructed literal expected paths (via the SAME mocked
100
+ // TEST_HOME this file's own homedir() mock uses, but NOT derived from
101
+ // COMPANION_AGENT_TARGETS itself) — a code-review pass on an earlier
102
+ // version of this test caught that comparing only against
103
+ // COMPANION_AGENT_TARGETS['claude-code'].dir proves "different from
104
+ // claude-code," not "equals the actual intended copilot/opencode value";
105
+ // a typo in the map (e.g. singular '.copilot/agent') would have still
106
+ // passed the old assertion.
107
+ expect(path.dirname(copilotResult.subagentPath ?? '')).toBe(path.join(TEST_HOME, '.copilot', 'agents'));
108
+ expect(path.dirname(opencodeResult.subagentPath ?? '')).toBe(path.join(TEST_HOME, '.config', 'opencode', 'agents'));
109
+ // Belt-and-suspenders: still confirm both differ from claude-code's dir.
110
+ expect(path.dirname(copilotResult.subagentPath ?? '')).not.toBe(COMPANION_AGENT_TARGETS['claude-code'].dir);
111
+ expect(path.dirname(opencodeResult.subagentPath ?? '')).not.toBe(COMPANION_AGENT_TARGETS['claude-code'].dir);
112
+ });
113
+ it('does not write any companion-subagent file when subagentContent is undefined, regardless of client', async () => {
114
+ const { skillsDir, installPath } = await freshInstallPath('no-subagent');
115
+ const result = await writeInstallFiles(installPath, skillsDir, 'my-skill', '# hello', [], undefined, 'copilot');
116
+ expect(result.subagentPath).toBeUndefined();
117
+ });
118
+ });
119
+ /**
120
+ * SMI-5982 (Wave 6): antigravity's companion-agent dir is a RELATIVE path
121
+ * (`.agents/agents`, project-scoped per the plan's Step 1 — no existing
122
+ * global-vs-project distinction to hook into) resolved against
123
+ * `process.cwd()`, unlike every other client's `homedir()`-anchored
124
+ * absolute dir. This describe block is isolated from the rest of the file:
125
+ * each test chdir's into its own fresh tmp directory (never TEST_HOME, and
126
+ * never the real repo checkout) and restores the original cwd in
127
+ * `afterEach` even on assertion failure, so a broken assertion can never
128
+ * leave the whole test PROCESS's cwd corrupted for later tests/files.
129
+ */
130
+ describe('writeInstallFiles companion-subagent path for antigravity (directory-package, SMI-5982 Wave 6)', () => {
131
+ let originalCwd;
132
+ let projectDir;
133
+ beforeEach(async () => {
134
+ originalCwd = process.cwd();
135
+ projectDir = await fs.mkdtemp(path.join(os.tmpdir(), 'skillsmith-antigravity-cwd-'));
136
+ process.chdir(projectDir);
137
+ });
138
+ afterEach(async () => {
139
+ process.chdir(originalCwd);
140
+ await fs.rm(projectDir, { recursive: true, force: true }).catch(() => { });
141
+ });
142
+ it('writes agent.md inside a skill-named subdirectory when companionBaseDir is passed explicitly (SMI-5982 code-review fix #1)', async () => {
143
+ const { skillsDir, installPath } = await freshInstallPath('antigravity-write');
144
+ const result = await writeInstallFiles(installPath, skillsDir, 'my-skill', '# hello', [], '---\nname: my-skill-specialist\n---\nbody', 'antigravity',
145
+ // PR-review follow-up: writeInstallFiles() no longer falls back to
146
+ // process.cwd() itself when companionBaseDir is omitted — an explicit
147
+ // value (here, this describe block's chdir target) is required for
148
+ // directory-package clients. See the dedicated "omitted
149
+ // companionBaseDir" test below for the fail-closed case.
150
+ projectDir);
151
+ // SMI-5982 code-review fix #1: resolveCompanionAgentPath() resolves
152
+ // antigravity's relative dir against the explicit baseDir BEFORE
153
+ // returning — so subagentPath is ABSOLUTE, not the raw relative string.
154
+ // Independently verify the REAL file via an absolute path built from the
155
+ // known projectDir (not derived from result.subagentPath, so a bug that
156
+ // silently mis-resolved the value would still be caught).
157
+ const expectedRelativePath = path.join('.agents', 'agents', 'my-skill', 'agent.md');
158
+ const expectedAbsolutePath = path.join(projectDir, expectedRelativePath);
159
+ expect(result.subagentPath).toBe(expectedAbsolutePath);
160
+ expect(await fs.readFile(expectedAbsolutePath, 'utf8')).toBe('---\nname: my-skill-specialist\n---\nbody');
161
+ // Directory-package structure: agent.md lives INSIDE a subdirectory
162
+ // named after the skill, not directly inside the agents dir.
163
+ expect(path.basename(path.dirname(expectedAbsolutePath))).toBe('my-skill');
164
+ });
165
+ it('omitting companionBaseDir for antigravity now rejects the install instead of silently defaulting to process.cwd() (PR-review follow-up)', async () => {
166
+ const { skillsDir, installPath } = await freshInstallPath('antigravity-omitted-basedir');
167
+ await expect(writeInstallFiles(installPath, skillsDir, 'my-skill', '# hello', [], '---\nname: my-skill-specialist\n---\nbody', 'antigravity'
168
+ // companionBaseDir omitted — must now throw (fail closed), not
169
+ // resolve against process.cwd(). SKILL.md IS written before this
170
+ // point (the companion-agent step runs last), but writeInstallFiles'
171
+ // existing rollback-on-failure logic unwinds installPath entirely on
172
+ // any thrown error — so nothing survives on disk after the throw.
173
+ )).rejects.toThrow(/directory-package mode.*explicit baseDir is required/s);
174
+ await expect(fs.access(installPath)).rejects.toThrow();
175
+ });
176
+ it('writes agent.md resolved against an explicit companionBaseDir, not process.cwd() (SMI-5982 code-review fix #1)', async () => {
177
+ // Deliberately DIFFERENT from projectDir (this block's chdir target) to
178
+ // prove companionBaseDir — not the ambient cwd — drives resolution. This
179
+ // is exactly the MCP-server scenario the fix targets: a long-running
180
+ // process whose own cwd does not track the caller's real project.
181
+ const explicitBaseDir = await fs.mkdtemp(path.join(os.tmpdir(), 'skillsmith-antigravity-explicit-basedir-'));
182
+ try {
183
+ const { skillsDir, installPath } = await freshInstallPath('antigravity-explicit-basedir');
184
+ const result = await writeInstallFiles(installPath, skillsDir, 'my-skill', '# hello', [], '---\nname: my-skill-specialist\n---\nbody', 'antigravity', explicitBaseDir);
185
+ const expectedAbsolutePath = path.join(explicitBaseDir, '.agents', 'agents', 'my-skill', 'agent.md');
186
+ expect(result.subagentPath).toBe(expectedAbsolutePath);
187
+ expect(result.subagentPath?.startsWith(projectDir)).toBe(false);
188
+ expect(await fs.readFile(expectedAbsolutePath, 'utf8')).toBe('---\nname: my-skill-specialist\n---\nbody');
189
+ }
190
+ finally {
191
+ await fs.rm(explicitBaseDir, { recursive: true, force: true }).catch(() => { });
192
+ }
193
+ });
194
+ it('a safeWriteFile failure on the companion-agent path does not crash, and never force-removes a non-empty per-skill directory', async () => {
195
+ // Reachable, non-mocked failure mode for the LAST step in
196
+ // writeInstallFiles's try block (companion-agent write): a symlink
197
+ // already sitting at the exact target path. safeWriteFile's O_NOFOLLOW
198
+ // open() refuses it (SymlinkError), so the rollback branch added in
199
+ // SMI-5982 runs with subagentPath already assigned. The per-skill
200
+ // directory is NOT empty (the symlink itself is still inside it), so
201
+ // the rollback's rmdir() must be a safe no-op here, never a force-delete
202
+ // — this proves the fix degrades safely rather than that it always
203
+ // reclaims disk space (an EMPTY orphaned directory can only arise from a
204
+ // transient I/O failure between mkdir and the write, not reproducible
205
+ // deterministically without mocking fs internals).
206
+ const { skillsDir, installPath } = await freshInstallPath('antigravity-symlink');
207
+ const agentSkillDir = path.join(projectDir, '.agents', 'agents', 'my-skill');
208
+ await fs.mkdir(agentSkillDir, { recursive: true });
209
+ await fs.symlink('/nonexistent-target', path.join(agentSkillDir, 'agent.md'));
210
+ await expect(writeInstallFiles(installPath, skillsDir, 'my-skill', '# hello', [], '---\nname: my-skill-specialist\n---\nbody', 'antigravity',
211
+ // PR-review follow-up: explicit now that writeInstallFiles() no
212
+ // longer defaults a missing companionBaseDir to process.cwd() —
213
+ // required so this test still reaches the symlink failure it is
214
+ // actually exercising, rather than the (also-now-thrown)
215
+ // required-baseDir guard.
216
+ projectDir)).rejects.toThrow(/symlink/i);
217
+ // The directory (and its symlink) must still exist — rollback did not
218
+ // blindly force-delete non-empty content.
219
+ const stats = await fs.lstat(agentSkillDir);
220
+ expect(stats.isDirectory()).toBe(true);
221
+ });
222
+ it('rejects a path-traversal skillName ("..") for the companion-agent path and rolls back the already-written SKILL.md (SMI-5982 code-review fix #2)', async () => {
223
+ // resolveCompanionAgentPath()'s own directory-package validation (fix #2)
224
+ // is the last line of defense here: this test passes a malicious
225
+ // skillName distinct from what installPath was built from, exactly the
226
+ // "a future caller bypasses upstream sanitization" scenario the fix's
227
+ // doc comment calls out.
228
+ const { skillsDir, installPath } = await freshInstallPath('antigravity-traversal');
229
+ await expect(writeInstallFiles(installPath, skillsDir, '..', '# hello', [], '---\nname: specialist\n---\nbody', 'antigravity',
230
+ // PR-review follow-up: explicit now that writeInstallFiles() no
231
+ // longer defaults a missing companionBaseDir to process.cwd() —
232
+ // required so this test still reaches the skillName traversal
233
+ // guard it is actually exercising, rather than the
234
+ // (also-now-thrown) required-baseDir guard.
235
+ projectDir)).rejects.toThrow(/Unsafe skill name for directory-package companion path/);
236
+ // Rollback: the existing catch block in writeInstallFiles() already
237
+ // covers this — SKILL.md was written before the throw (subagentPath is
238
+ // resolved last), so it (and installPath itself) must be gone. Nothing
239
+ // was ever created under the companion-agent dir, since the throw
240
+ // happens BEFORE any fs.mkdir/write for that path.
241
+ await expect(fs.access(installPath)).rejects.toThrow();
242
+ const agentsParentDir = path.join(projectDir, '.agents');
243
+ await expect(fs.access(agentsParentDir)).rejects.toThrow();
244
+ });
245
+ });
246
+ //# sourceMappingURL=skill-installation.io.client-agent-path.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-installation.io.client-agent-path.test.js","sourceRoot":"","sources":["../../../../tests/unit/services/skill-installation.io.client-agent-path.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * SMI-5982 code-review fix #1 (BLOCKING, cwd-dependent resolution):
3
+ * `SkillInstallationService`'s `companionBaseDir` constructor param must
4
+ * thread all the way through `install()` -> `writeInstallFiles()` ->
5
+ * `resolveCompanionAgentPath()` so the Antigravity companion-agent file
6
+ * lands under an explicitly-passed root, not whatever `process.cwd()`
7
+ * happens to be at the moment the write actually runs — the exact hazard
8
+ * for a long-running MCP server whose cwd is fixed at launch and does not
9
+ * track the calling editor/agent's real project.
10
+ *
11
+ * `applyOptimization` (skill-installation.helpers.ts) is mocked to force a
12
+ * deterministic `subagentContent` without depending on the real
13
+ * TransformationService's content-shape heuristics — this test is about
14
+ * PATH WIRING, not optimization behavior, which is covered elsewhere.
15
+ */
16
+ export {};
17
+ //# sourceMappingURL=skill-installation.service.companion-basedir.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-installation.service.companion-basedir.test.d.ts","sourceRoot":"","sources":["../../../../tests/unit/services/skill-installation.service.companion-basedir.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG"}