@skillsmith/core 0.4.14 → 0.4.15

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 (214) hide show
  1. package/README.md +2 -0
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/src/api/client.d.ts +1 -0
  4. package/dist/src/api/client.d.ts.map +1 -1
  5. package/dist/src/api/client.health.d.ts +26 -0
  6. package/dist/src/api/client.health.d.ts.map +1 -0
  7. package/dist/src/api/client.health.js +74 -0
  8. package/dist/src/api/client.health.js.map +1 -0
  9. package/dist/src/api/client.js +3 -51
  10. package/dist/src/api/client.js.map +1 -1
  11. package/dist/src/db/createDatabase.d.ts +9 -1
  12. package/dist/src/db/createDatabase.d.ts.map +1 -1
  13. package/dist/src/db/createDatabase.js +9 -1
  14. package/dist/src/db/createDatabase.js.map +1 -1
  15. package/dist/src/db/drivers/sqljsDriver.d.ts.map +1 -1
  16. package/dist/src/db/drivers/sqljsDriver.js +5 -2
  17. package/dist/src/db/drivers/sqljsDriver.js.map +1 -1
  18. package/dist/src/db/migrations/v5b-change-type.d.ts +19 -0
  19. package/dist/src/db/migrations/v5b-change-type.d.ts.map +1 -0
  20. package/dist/src/db/migrations/v5b-change-type.js +22 -0
  21. package/dist/src/db/migrations/v5b-change-type.js.map +1 -0
  22. package/dist/src/db/migrations/v6-advisories.d.ts +32 -0
  23. package/dist/src/db/migrations/v6-advisories.d.ts.map +1 -0
  24. package/dist/src/db/migrations/v6-advisories.js +53 -0
  25. package/dist/src/db/migrations/v6-advisories.js.map +1 -0
  26. package/dist/src/db/migrations/v7-compatibility.d.ts +21 -0
  27. package/dist/src/db/migrations/v7-compatibility.d.ts.map +1 -0
  28. package/dist/src/db/migrations/v7-compatibility.js +23 -0
  29. package/dist/src/db/migrations/v7-compatibility.js.map +1 -0
  30. package/dist/src/db/migrations/v8-co-installs.d.ts +21 -0
  31. package/dist/src/db/migrations/v8-co-installs.d.ts.map +1 -0
  32. package/dist/src/db/migrations/v8-co-installs.js +33 -0
  33. package/dist/src/db/migrations/v8-co-installs.js.map +1 -0
  34. package/dist/src/db/schema.d.ts +5 -16
  35. package/dist/src/db/schema.d.ts.map +1 -1
  36. package/dist/src/db/schema.js +37 -22
  37. package/dist/src/db/schema.js.map +1 -1
  38. package/dist/src/exports/repositories.d.ts +5 -0
  39. package/dist/src/exports/repositories.d.ts.map +1 -1
  40. package/dist/src/exports/repositories.js +17 -0
  41. package/dist/src/exports/repositories.js.map +1 -1
  42. package/dist/src/exports/types.d.ts +1 -1
  43. package/dist/src/exports/types.d.ts.map +1 -1
  44. package/dist/src/exports/types.js.map +1 -1
  45. package/dist/src/indexer/SkillParser.d.ts +2 -0
  46. package/dist/src/indexer/SkillParser.d.ts.map +1 -1
  47. package/dist/src/indexer/SkillParser.js.map +1 -1
  48. package/dist/src/learning/PatternStore.d.ts +0 -2
  49. package/dist/src/learning/PatternStore.d.ts.map +1 -1
  50. package/dist/src/learning/PatternStore.helpers.d.ts +19 -1
  51. package/dist/src/learning/PatternStore.helpers.d.ts.map +1 -1
  52. package/dist/src/learning/PatternStore.helpers.js +51 -0
  53. package/dist/src/learning/PatternStore.helpers.js.map +1 -1
  54. package/dist/src/learning/PatternStore.js +5 -37
  55. package/dist/src/learning/PatternStore.js.map +1 -1
  56. package/dist/src/repositories/AdvisoryRepository.d.ts +80 -0
  57. package/dist/src/repositories/AdvisoryRepository.d.ts.map +1 -0
  58. package/dist/src/repositories/AdvisoryRepository.js +128 -0
  59. package/dist/src/repositories/AdvisoryRepository.js.map +1 -0
  60. package/dist/src/repositories/AdvisoryRepository.test.d.ts +6 -0
  61. package/dist/src/repositories/AdvisoryRepository.test.d.ts.map +1 -0
  62. package/dist/src/repositories/AdvisoryRepository.test.js +149 -0
  63. package/dist/src/repositories/AdvisoryRepository.test.js.map +1 -0
  64. package/dist/src/repositories/CoInstallRepository.d.ts +68 -0
  65. package/dist/src/repositories/CoInstallRepository.d.ts.map +1 -0
  66. package/dist/src/repositories/CoInstallRepository.js +122 -0
  67. package/dist/src/repositories/CoInstallRepository.js.map +1 -0
  68. package/dist/src/repositories/SkillRepository.d.ts.map +1 -1
  69. package/dist/src/repositories/SkillRepository.js +16 -5
  70. package/dist/src/repositories/SkillRepository.js.map +1 -1
  71. package/dist/src/services/SearchService.helpers.d.ts.map +1 -1
  72. package/dist/src/services/SearchService.helpers.js +4 -0
  73. package/dist/src/services/SearchService.helpers.js.map +1 -1
  74. package/dist/src/services/SearchService.types.d.ts +1 -0
  75. package/dist/src/services/SearchService.types.d.ts.map +1 -1
  76. package/dist/src/services/TaskRunner.d.ts +5 -81
  77. package/dist/src/services/TaskRunner.d.ts.map +1 -1
  78. package/dist/src/services/TaskRunner.js +7 -68
  79. package/dist/src/services/TaskRunner.js.map +1 -1
  80. package/dist/src/services/TaskRunner.process.d.ts +33 -0
  81. package/dist/src/services/TaskRunner.process.d.ts.map +1 -0
  82. package/dist/src/services/TaskRunner.process.js +70 -0
  83. package/dist/src/services/TaskRunner.process.js.map +1 -0
  84. package/dist/src/services/TaskRunner.types.d.ts +76 -0
  85. package/dist/src/services/TaskRunner.types.d.ts.map +1 -0
  86. package/dist/src/services/TaskRunner.types.js +22 -0
  87. package/dist/src/services/TaskRunner.types.js.map +1 -0
  88. package/dist/src/services/__tests__/TaskRunner.process.test.d.ts +13 -0
  89. package/dist/src/services/__tests__/TaskRunner.process.test.d.ts.map +1 -0
  90. package/dist/src/services/__tests__/TaskRunner.process.test.js +91 -0
  91. package/dist/src/services/__tests__/TaskRunner.process.test.js.map +1 -0
  92. package/dist/src/services/quarantine/QuarantineService.d.ts +3 -24
  93. package/dist/src/services/quarantine/QuarantineService.d.ts.map +1 -1
  94. package/dist/src/services/quarantine/QuarantineService.js +8 -205
  95. package/dist/src/services/quarantine/QuarantineService.js.map +1 -1
  96. package/dist/src/services/quarantine/QuarantineService.multiapproval.d.ts +57 -0
  97. package/dist/src/services/quarantine/QuarantineService.multiapproval.d.ts.map +1 -0
  98. package/dist/src/services/quarantine/QuarantineService.multiapproval.js +211 -0
  99. package/dist/src/services/quarantine/QuarantineService.multiapproval.js.map +1 -0
  100. package/dist/src/session/SessionManager.d.ts +2 -33
  101. package/dist/src/session/SessionManager.d.ts.map +1 -1
  102. package/dist/src/session/SessionManager.js +14 -238
  103. package/dist/src/session/SessionManager.js.map +1 -1
  104. package/dist/src/session/SessionManager.memory.d.ts +67 -0
  105. package/dist/src/session/SessionManager.memory.d.ts.map +1 -0
  106. package/dist/src/session/SessionManager.memory.js +262 -0
  107. package/dist/src/session/SessionManager.memory.js.map +1 -0
  108. package/dist/src/sync/SyncEngine.d.ts +13 -1
  109. package/dist/src/sync/SyncEngine.d.ts.map +1 -1
  110. package/dist/src/sync/SyncEngine.js +50 -1
  111. package/dist/src/sync/SyncEngine.js.map +1 -1
  112. package/dist/src/testing/MultiLLMProvider.d.ts +5 -6
  113. package/dist/src/testing/MultiLLMProvider.d.ts.map +1 -1
  114. package/dist/src/testing/MultiLLMProvider.js +18 -130
  115. package/dist/src/testing/MultiLLMProvider.js.map +1 -1
  116. package/dist/src/testing/MultiLLMProvider.metrics.d.ts +33 -0
  117. package/dist/src/testing/MultiLLMProvider.metrics.d.ts.map +1 -0
  118. package/dist/src/testing/MultiLLMProvider.metrics.js +87 -0
  119. package/dist/src/testing/MultiLLMProvider.metrics.js.map +1 -0
  120. package/dist/src/testing/MultiLLMProvider.selection.d.ts +77 -0
  121. package/dist/src/testing/MultiLLMProvider.selection.d.ts.map +1 -0
  122. package/dist/src/testing/MultiLLMProvider.selection.js +151 -0
  123. package/dist/src/testing/MultiLLMProvider.selection.js.map +1 -0
  124. package/dist/src/types/skill.d.ts +10 -0
  125. package/dist/src/types/skill.d.ts.map +1 -1
  126. package/dist/src/types.d.ts +30 -0
  127. package/dist/src/types.d.ts.map +1 -1
  128. package/dist/src/versioning/change-classifier.d.ts +38 -0
  129. package/dist/src/versioning/change-classifier.d.ts.map +1 -0
  130. package/dist/src/versioning/change-classifier.js +187 -0
  131. package/dist/src/versioning/change-classifier.js.map +1 -0
  132. package/dist/src/versioning/change-classifier.test.d.ts +6 -0
  133. package/dist/src/versioning/change-classifier.test.d.ts.map +1 -0
  134. package/dist/src/versioning/change-classifier.test.js +275 -0
  135. package/dist/src/versioning/change-classifier.test.js.map +1 -0
  136. package/dist/src/versioning/update-risk.d.ts +50 -0
  137. package/dist/src/versioning/update-risk.d.ts.map +1 -0
  138. package/dist/src/versioning/update-risk.js +80 -0
  139. package/dist/src/versioning/update-risk.js.map +1 -0
  140. package/dist/src/versioning/update-risk.test.d.ts +6 -0
  141. package/dist/src/versioning/update-risk.test.d.ts.map +1 -0
  142. package/dist/src/versioning/update-risk.test.js +200 -0
  143. package/dist/src/versioning/update-risk.test.js.map +1 -0
  144. package/dist/tests/AuditLogger.edge-cases.test.d.ts +10 -0
  145. package/dist/tests/AuditLogger.edge-cases.test.d.ts.map +1 -0
  146. package/dist/tests/AuditLogger.edge-cases.test.js +183 -0
  147. package/dist/tests/AuditLogger.edge-cases.test.js.map +1 -0
  148. package/dist/tests/CacheManager.test.d.ts +9 -0
  149. package/dist/tests/CacheManager.test.d.ts.map +1 -0
  150. package/dist/tests/CacheManager.test.js +163 -0
  151. package/dist/tests/CacheManager.test.js.map +1 -0
  152. package/dist/tests/GitHubIndexer.edge-cases.test.d.ts +10 -0
  153. package/dist/tests/GitHubIndexer.edge-cases.test.d.ts.map +1 -0
  154. package/dist/tests/GitHubIndexer.edge-cases.test.js +255 -0
  155. package/dist/tests/GitHubIndexer.edge-cases.test.js.map +1 -0
  156. package/dist/tests/SearchService.test.js +71 -0
  157. package/dist/tests/SearchService.test.js.map +1 -1
  158. package/dist/tests/SkillVersionRepository.test.d.ts +0 -11
  159. package/dist/tests/SkillVersionRepository.test.d.ts.map +1 -1
  160. package/dist/tests/SkillVersionRepository.test.js +131 -194
  161. package/dist/tests/SkillVersionRepository.test.js.map +1 -1
  162. package/dist/tests/api/client.health.test.d.ts +15 -0
  163. package/dist/tests/api/client.health.test.d.ts.map +1 -0
  164. package/dist/tests/api/client.health.test.js +111 -0
  165. package/dist/tests/api/client.health.test.js.map +1 -0
  166. package/dist/tests/db/betterSqlite3Driver.test.d.ts +8 -0
  167. package/dist/tests/db/betterSqlite3Driver.test.d.ts.map +1 -0
  168. package/dist/tests/db/betterSqlite3Driver.test.js +88 -0
  169. package/dist/tests/db/betterSqlite3Driver.test.js.map +1 -0
  170. package/dist/tests/db/database-abstraction.test.js +12 -0
  171. package/dist/tests/db/database-abstraction.test.js.map +1 -1
  172. package/dist/tests/db/schema-migrations.test.d.ts +10 -0
  173. package/dist/tests/db/schema-migrations.test.d.ts.map +1 -0
  174. package/dist/tests/db/schema-migrations.test.js +134 -0
  175. package/dist/tests/db/schema-migrations.test.js.map +1 -0
  176. package/dist/tests/db/sqljsDriver.test.d.ts +9 -0
  177. package/dist/tests/db/sqljsDriver.test.d.ts.map +1 -0
  178. package/dist/tests/db/sqljsDriver.test.js +75 -0
  179. package/dist/tests/db/sqljsDriver.test.js.map +1 -0
  180. package/dist/tests/helpers/database.d.ts +32 -0
  181. package/dist/tests/helpers/database.d.ts.map +1 -0
  182. package/dist/tests/helpers/database.js +54 -0
  183. package/dist/tests/helpers/database.js.map +1 -0
  184. package/dist/tests/learning/PatternStore.helpers.test.d.ts +17 -0
  185. package/dist/tests/learning/PatternStore.helpers.test.d.ts.map +1 -0
  186. package/dist/tests/learning/PatternStore.helpers.test.js +301 -0
  187. package/dist/tests/learning/PatternStore.helpers.test.js.map +1 -0
  188. package/dist/tests/repositories/CoInstallRepository.test.d.ts +9 -0
  189. package/dist/tests/repositories/CoInstallRepository.test.d.ts.map +1 -0
  190. package/dist/tests/repositories/CoInstallRepository.test.js +126 -0
  191. package/dist/tests/repositories/CoInstallRepository.test.js.map +1 -0
  192. package/dist/tests/routing/LanguageRouter.test.d.ts +9 -0
  193. package/dist/tests/routing/LanguageRouter.test.d.ts.map +1 -0
  194. package/dist/tests/routing/LanguageRouter.test.js +150 -0
  195. package/dist/tests/routing/LanguageRouter.test.js.map +1 -0
  196. package/dist/tests/session/SessionManager.memory.test.d.ts +11 -0
  197. package/dist/tests/session/SessionManager.memory.test.d.ts.map +1 -0
  198. package/dist/tests/session/SessionManager.memory.test.js +219 -0
  199. package/dist/tests/session/SessionManager.memory.test.js.map +1 -0
  200. package/dist/tests/sync/SyncEngine.test.js +32 -18
  201. package/dist/tests/sync/SyncEngine.test.js.map +1 -1
  202. package/dist/tests/testing/MultiLLMProvider.metrics.test.d.ts +13 -0
  203. package/dist/tests/testing/MultiLLMProvider.metrics.test.d.ts.map +1 -0
  204. package/dist/tests/testing/MultiLLMProvider.metrics.test.js +149 -0
  205. package/dist/tests/testing/MultiLLMProvider.metrics.test.js.map +1 -0
  206. package/dist/tests/testing/MultiLLMProvider.selection.test.d.ts +15 -0
  207. package/dist/tests/testing/MultiLLMProvider.selection.test.d.ts.map +1 -0
  208. package/dist/tests/testing/MultiLLMProvider.selection.test.js +249 -0
  209. package/dist/tests/testing/MultiLLMProvider.selection.test.js.map +1 -0
  210. package/dist/tests/unit/quarantine-query-builder.test.d.ts +10 -0
  211. package/dist/tests/unit/quarantine-query-builder.test.d.ts.map +1 -0
  212. package/dist/tests/unit/quarantine-query-builder.test.js +157 -0
  213. package/dist/tests/unit/quarantine-query-builder.test.js.map +1 -0
  214. package/package.json +1 -1
@@ -1,230 +1,167 @@
1
1
  /**
2
- * @fileoverview Unit tests for SkillVersionRepository
3
- * @see SMI-skill-version-tracking Wave 1
2
+ * SkillVersionRepository Tests
4
3
  *
5
- * Tests cover:
6
- * - recordVersion (idempotency via INSERT OR IGNORE)
7
- * - getLatestVersion (returns newest row or null)
8
- * - getVersionHistory (ordered DESC, respects limit)
9
- * - getVersionByHash (exact lookup)
10
- * - pruneVersions (keeps N most-recent rows)
4
+ * Tests for skill version hash tracking (SMI-skill-version-tracking Wave 1).
11
5
  */
12
6
  import { describe, it, expect, beforeEach, afterEach } from 'vitest';
13
- import { createDatabase, closeDatabase } from '../src/db/schema.js';
7
+ import { createTestDatabase, closeDatabase } from './helpers/database.js';
14
8
  import { SkillVersionRepository } from '../src/repositories/SkillVersionRepository.js';
15
- // ---------------------------------------------------------------------------
16
- // Helpers
17
- // ---------------------------------------------------------------------------
18
- function makeHash(n) {
19
- return n.toString(16).padStart(64, '0');
20
- }
21
- // ---------------------------------------------------------------------------
22
- // Suite
23
- // ---------------------------------------------------------------------------
24
9
  describe('SkillVersionRepository', () => {
25
10
  let db;
26
11
  let repo;
27
12
  beforeEach(() => {
28
- db = createDatabase(':memory:');
13
+ db = createTestDatabase();
29
14
  repo = new SkillVersionRepository(db);
30
15
  });
31
16
  afterEach(() => {
32
17
  closeDatabase(db);
33
18
  });
34
- // -------------------------------------------------------------------------
35
- // getLatestVersion
36
- // -------------------------------------------------------------------------
19
+ describe('recordVersion', () => {
20
+ it('should insert a new version record', async () => {
21
+ await repo.recordVersion('author/skill-a', 'abc123hash', '1.0.0');
22
+ const latest = await repo.getLatestVersion('author/skill-a');
23
+ expect(latest).not.toBeNull();
24
+ expect(latest.skill_id).toBe('author/skill-a');
25
+ expect(latest.content_hash).toBe('abc123hash');
26
+ expect(latest.semver).toBe('1.0.0');
27
+ });
28
+ it('should be idempotent — duplicate (skill_id, content_hash) is silently ignored', async () => {
29
+ await repo.recordVersion('author/skill-a', 'abc123hash');
30
+ await repo.recordVersion('author/skill-a', 'abc123hash');
31
+ const history = await repo.getVersionHistory('author/skill-a', 50);
32
+ expect(history.length).toBe(1);
33
+ });
34
+ it('should store different hashes for the same skill', async () => {
35
+ await repo.recordVersion('author/skill-a', 'hash-v1');
36
+ await repo.recordVersion('author/skill-a', 'hash-v2');
37
+ const history = await repo.getVersionHistory('author/skill-a', 50);
38
+ expect(history.length).toBe(2);
39
+ });
40
+ it('should store null semver when omitted', async () => {
41
+ await repo.recordVersion('author/skill-a', 'hash-v1');
42
+ const latest = await repo.getLatestVersion('author/skill-a');
43
+ expect(latest.semver).toBeNull();
44
+ });
45
+ it('should store optional metadata', async () => {
46
+ const meta = JSON.stringify({ source: 'registry' });
47
+ await repo.recordVersion('author/skill-a', 'hash-v1', '1.0.0', meta);
48
+ const latest = await repo.getLatestVersion('author/skill-a');
49
+ expect(latest.metadata).toBe(meta);
50
+ });
51
+ });
37
52
  describe('getLatestVersion', () => {
38
- it('returns null when no versions recorded', async () => {
39
- const result = await repo.getLatestVersion('unknown/skill');
53
+ it('should return null when no versions recorded', async () => {
54
+ const result = await repo.getLatestVersion('nonexistent/skill');
40
55
  expect(result).toBeNull();
41
56
  });
42
- it('returns the single recorded version', async () => {
43
- await repo.recordVersion('author/skill', makeHash(1));
44
- const result = await repo.getLatestVersion('author/skill');
45
- expect(result).not.toBeNull();
46
- expect(result.content_hash).toBe(makeHash(1));
47
- });
48
- it('returns the most recently recorded version when multiple exist', async () => {
49
- // Insert with small delays to ensure recorded_at ordering
50
- await repo.recordVersion('author/skill', makeHash(1));
51
- // Override recorded_at on row 1 to be in the past
52
- db.prepare(`UPDATE skill_versions SET recorded_at = recorded_at - 100 WHERE content_hash = ?`).run(makeHash(1));
53
- await repo.recordVersion('author/skill', makeHash(2));
54
- const result = await repo.getLatestVersion('author/skill');
55
- expect(result.content_hash).toBe(makeHash(2));
56
- });
57
- it('does not return versions for other skills', async () => {
58
- await repo.recordVersion('other/skill', makeHash(99));
59
- const result = await repo.getLatestVersion('author/skill');
57
+ it('should return the most recently recorded version', async () => {
58
+ await repo.recordVersion('author/skill-a', 'hash-v1');
59
+ // Backdate the first row so the second has a later recorded_at
60
+ db.prepare(`UPDATE skill_versions SET recorded_at = recorded_at - 10 WHERE content_hash = ?`).run('hash-v1');
61
+ await repo.recordVersion('author/skill-a', 'hash-v2');
62
+ const latest = await repo.getLatestVersion('author/skill-a');
63
+ expect(latest.content_hash).toBe('hash-v2');
64
+ });
65
+ it('should not return versions from a different skill', async () => {
66
+ await repo.recordVersion('author/skill-b', 'hash-b');
67
+ const result = await repo.getLatestVersion('author/skill-a');
60
68
  expect(result).toBeNull();
61
69
  });
62
70
  });
63
- // -------------------------------------------------------------------------
64
- // recordVersion
65
- // -------------------------------------------------------------------------
66
- describe('recordVersion', () => {
67
- it('inserts a new version row', async () => {
68
- await repo.recordVersion('author/skill', makeHash(1));
69
- const history = await repo.getVersionHistory('author/skill');
70
- expect(history).toHaveLength(1);
71
- expect(history[0].content_hash).toBe(makeHash(1));
72
- });
73
- it('is idempotent — duplicate (skillId, hash) is silently ignored', async () => {
74
- await repo.recordVersion('author/skill', makeHash(1));
75
- await repo.recordVersion('author/skill', makeHash(1));
76
- const history = await repo.getVersionHistory('author/skill');
77
- expect(history).toHaveLength(1);
78
- });
79
- it('stores semver when provided', async () => {
80
- await repo.recordVersion('author/skill', makeHash(1), '1.2.3');
81
- const row = await repo.getLatestVersion('author/skill');
82
- expect(row.semver).toBe('1.2.3');
83
- });
84
- it('stores metadata when provided', async () => {
85
- await repo.recordVersion('author/skill', makeHash(1), undefined, '{"source":"test"}');
86
- const row = await repo.getLatestVersion('author/skill');
87
- expect(row.metadata).toBe('{"source":"test"}');
88
- });
89
- it('records recorded_at as a Unix timestamp', async () => {
90
- const before = Math.floor(Date.now() / 1000);
91
- await repo.recordVersion('author/skill', makeHash(1));
92
- const after = Math.floor(Date.now() / 1000) + 1;
93
- const row = await repo.getLatestVersion('author/skill');
94
- expect(row.recorded_at).toBeGreaterThanOrEqual(before);
95
- expect(row.recorded_at).toBeLessThanOrEqual(after);
96
- });
97
- it('prunes down to keepCount after insertion', async () => {
98
- // Insert 5 unique hashes with keepCount=3
99
- for (let i = 1; i <= 5; i++) {
100
- await repo.recordVersion('author/skill', makeHash(i), undefined, undefined, 3);
101
- // Push older rows further back so ordering is deterministic
102
- db.prepare(`UPDATE skill_versions SET recorded_at = recorded_at - ? WHERE content_hash = ?`).run((5 - i) * 10, makeHash(i));
71
+ describe('getVersionHistory', () => {
72
+ it('should return empty array when no versions recorded', async () => {
73
+ const history = await repo.getVersionHistory('nonexistent/skill');
74
+ expect(history).toEqual([]);
75
+ });
76
+ it('should return versions ordered newest first (DESC)', async () => {
77
+ await repo.recordVersion('author/skill-a', 'hash-v1');
78
+ db.prepare(`UPDATE skill_versions SET recorded_at = recorded_at - 10 WHERE content_hash = ?`).run('hash-v1');
79
+ await repo.recordVersion('author/skill-a', 'hash-v2');
80
+ const history = await repo.getVersionHistory('author/skill-a');
81
+ expect(history[0].content_hash).toBe('hash-v2');
82
+ expect(history[1].content_hash).toBe('hash-v1');
83
+ });
84
+ it('should respect the limit parameter', async () => {
85
+ for (let i = 0; i < 5; i++) {
86
+ await repo.recordVersion('author/skill-a', `hash-v${i}`);
103
87
  }
104
- const history = await repo.getVersionHistory('author/skill', 100);
105
- expect(history.length).toBeLessThanOrEqual(3);
88
+ const history = await repo.getVersionHistory('author/skill-a', 3);
89
+ expect(history.length).toBe(3);
106
90
  });
107
- });
108
- // -------------------------------------------------------------------------
109
- // getVersionHistory
110
- // -------------------------------------------------------------------------
111
- describe('getVersionHistory', () => {
112
- it('returns empty array when no versions recorded', async () => {
113
- const history = await repo.getVersionHistory('author/skill');
114
- expect(history).toHaveLength(0);
115
- });
116
- it('returns versions ordered newest first', async () => {
117
- await repo.recordVersion('author/skill', makeHash(1));
118
- db.prepare(`UPDATE skill_versions SET recorded_at = recorded_at - 100 WHERE content_hash = ?`).run(makeHash(1));
119
- await repo.recordVersion('author/skill', makeHash(2));
120
- const history = await repo.getVersionHistory('author/skill');
121
- expect(history[0].content_hash).toBe(makeHash(2));
122
- expect(history[1].content_hash).toBe(makeHash(1));
123
- });
124
- it('respects the limit parameter', async () => {
125
- for (let i = 1; i <= 10; i++) {
126
- await repo.recordVersion('author/skill', makeHash(i));
127
- if (i > 1) {
128
- db.prepare(`UPDATE skill_versions SET recorded_at = recorded_at - ? WHERE content_hash = ?`).run((10 - i) * 10, makeHash(i));
129
- }
91
+ it('should default to limit 20', async () => {
92
+ for (let i = 0; i < 25; i++) {
93
+ await repo.recordVersion('author/skill-a', `hash-v${i}`);
130
94
  }
131
- const history = await repo.getVersionHistory('author/skill', 5);
132
- expect(history).toHaveLength(5);
95
+ const history = await repo.getVersionHistory('author/skill-a');
96
+ expect(history.length).toBe(20);
133
97
  });
134
- it('does not include rows from other skills', async () => {
135
- await repo.recordVersion('author/skill-a', makeHash(1));
136
- await repo.recordVersion('author/skill-b', makeHash(2));
98
+ it('should only return versions for the requested skill', async () => {
99
+ await repo.recordVersion('author/skill-a', 'hash-a');
100
+ await repo.recordVersion('author/skill-b', 'hash-b');
137
101
  const history = await repo.getVersionHistory('author/skill-a');
138
- expect(history).toHaveLength(1);
139
- expect(history[0].skill_id).toBe('author/skill-a');
102
+ expect(history.length).toBe(1);
103
+ expect(history[0].content_hash).toBe('hash-a');
140
104
  });
141
105
  });
142
- // -------------------------------------------------------------------------
143
- // getVersionByHash
144
- // -------------------------------------------------------------------------
145
106
  describe('getVersionByHash', () => {
146
- it('returns null when hash not found', async () => {
147
- const result = await repo.getVersionByHash('author/skill', makeHash(99));
148
- expect(result).toBeNull();
149
- });
150
- it('returns null when hash belongs to a different skill', async () => {
151
- await repo.recordVersion('other/skill', makeHash(1));
152
- const result = await repo.getVersionByHash('author/skill', makeHash(1));
153
- expect(result).toBeNull();
154
- });
155
- it('returns the matching row', async () => {
156
- await repo.recordVersion('author/skill', makeHash(1));
157
- const result = await repo.getVersionByHash('author/skill', makeHash(1));
158
- expect(result).not.toBeNull();
159
- expect(result.content_hash).toBe(makeHash(1));
160
- expect(result.skill_id).toBe('author/skill');
107
+ it('should return the matching row', async () => {
108
+ await repo.recordVersion('author/skill-a', 'target-hash', '2.0.0');
109
+ const row = await repo.getVersionByHash('author/skill-a', 'target-hash');
110
+ expect(row).not.toBeNull();
111
+ expect(row.content_hash).toBe('target-hash');
112
+ expect(row.semver).toBe('2.0.0');
113
+ });
114
+ it('should return null when hash not found', async () => {
115
+ const row = await repo.getVersionByHash('author/skill-a', 'nonexistent-hash');
116
+ expect(row).toBeNull();
117
+ });
118
+ it('should return null when skill_id does not match', async () => {
119
+ await repo.recordVersion('author/skill-a', 'shared-hash');
120
+ const row = await repo.getVersionByHash('author/skill-b', 'shared-hash');
121
+ expect(row).toBeNull();
161
122
  });
162
123
  });
163
- // -------------------------------------------------------------------------
164
- // pruneVersions
165
- // -------------------------------------------------------------------------
166
124
  describe('pruneVersions', () => {
167
- it('does nothing when row count is at or below keepCount', async () => {
168
- await repo.recordVersion('author/skill', makeHash(1));
169
- await repo.recordVersion('author/skill', makeHash(2));
170
- await repo.pruneVersions('author/skill', 5);
171
- const history = await repo.getVersionHistory('author/skill', 100);
172
- expect(history).toHaveLength(2);
173
- });
174
- it('removes oldest rows when count exceeds keepCount', async () => {
175
- for (let i = 1; i <= 5; i++) {
176
- await repo.recordVersion('author/skill', makeHash(i));
177
- db.prepare(`UPDATE skill_versions SET recorded_at = recorded_at - ? WHERE content_hash = ?`).run((5 - i) * 10, makeHash(i));
125
+ it('should retain at most keepCount rows per skill', async () => {
126
+ // Insert 55 distinct hashes
127
+ for (let i = 0; i < 55; i++) {
128
+ await repo.recordVersion('author/skill-a', `hash-${String(i).padStart(3, '0')}`);
129
+ }
130
+ await repo.pruneVersions('author/skill-a', 50);
131
+ const history = await repo.getVersionHistory('author/skill-a', 100);
132
+ expect(history.length).toBe(50);
133
+ });
134
+ it('should keep the most recent rows when pruning', async () => {
135
+ for (let i = 0; i < 5; i++) {
136
+ await repo.recordVersion('author/skill-a', `hash-${i}`);
137
+ // Space out recorded_at so ordering is deterministic
138
+ db.prepare(`UPDATE skill_versions SET recorded_at = ? WHERE content_hash = ?`).run(1000 + i, `hash-${i}`);
178
139
  }
179
- await repo.pruneVersions('author/skill', 3);
180
- const history = await repo.getVersionHistory('author/skill', 100);
181
- expect(history).toHaveLength(3);
182
- // Should keep the 3 most-recent (highest recorded_at values)
183
- // After our adjustments: hash(5) is newest, hash(4) is 2nd, etc.
140
+ await repo.pruneVersions('author/skill-a', 3);
141
+ const history = await repo.getVersionHistory('author/skill-a', 10);
142
+ // Newest 3: hash-4, hash-3, hash-2
184
143
  const hashes = history.map((r) => r.content_hash);
185
- expect(hashes).toContain(makeHash(5));
186
- });
187
- it('does not affect other skill rows', async () => {
188
- await repo.recordVersion('author/skill-a', makeHash(1));
189
- await repo.recordVersion('author/skill-a', makeHash(2));
190
- await repo.recordVersion('author/skill-b', makeHash(3));
191
- await repo.pruneVersions('author/skill-a', 1);
192
- const bHistory = await repo.getVersionHistory('author/skill-b', 100);
193
- expect(bHistory).toHaveLength(1);
194
- });
195
- });
196
- // -------------------------------------------------------------------------
197
- // Integration: update detection
198
- // -------------------------------------------------------------------------
199
- describe('update detection pattern', () => {
200
- it('detects when a skill has been updated since first sync', async () => {
201
- const skillId = 'author/my-skill';
202
- // Simulate first sync: record initial hash
203
- const initialHash = makeHash(100);
204
- await repo.recordVersion(skillId, initialHash);
205
- // Simulate second sync: record updated hash
206
- db.prepare(`UPDATE skill_versions SET recorded_at = recorded_at - 86400 WHERE skill_id = ?`).run(skillId);
207
- const updatedHash = makeHash(200);
208
- await repo.recordVersion(skillId, updatedHash);
209
- // Compare oldest (installed) vs latest (current registry)
210
- const history = await repo.getVersionHistory(skillId);
211
- const latest = history[0];
212
- const oldest = history[history.length - 1];
213
- expect(oldest.content_hash).toBe(initialHash);
214
- expect(latest.content_hash).toBe(updatedHash);
215
- expect(oldest.content_hash).not.toBe(latest.content_hash);
216
- });
217
- it('shows no update when skill content has not changed', async () => {
218
- const skillId = 'author/stable-skill';
219
- const hash = makeHash(42);
220
- // Record same hash twice (idempotent — only one row stored)
221
- await repo.recordVersion(skillId, hash);
222
- await repo.recordVersion(skillId, hash);
223
- const history = await repo.getVersionHistory(skillId);
224
- expect(history).toHaveLength(1);
225
- const latest = history[0];
226
- const oldest = history[history.length - 1];
227
- expect(oldest.content_hash).toBe(latest.content_hash);
144
+ expect(hashes).toContain('hash-4');
145
+ expect(hashes).toContain('hash-3');
146
+ expect(hashes).toContain('hash-2');
147
+ expect(hashes).not.toContain('hash-1');
148
+ expect(hashes).not.toContain('hash-0');
149
+ });
150
+ it('should not prune when row count is below keepCount', async () => {
151
+ await repo.recordVersion('author/skill-a', 'hash-v1');
152
+ await repo.recordVersion('author/skill-a', 'hash-v2');
153
+ await repo.pruneVersions('author/skill-a', 50);
154
+ const history = await repo.getVersionHistory('author/skill-a', 100);
155
+ expect(history.length).toBe(2);
156
+ });
157
+ it('should not affect other skills when pruning', async () => {
158
+ for (let i = 0; i < 55; i++) {
159
+ await repo.recordVersion('author/skill-a', `hash-a-${i}`);
160
+ }
161
+ await repo.recordVersion('author/skill-b', 'hash-b-1');
162
+ await repo.pruneVersions('author/skill-a', 50);
163
+ const historyB = await repo.getVersionHistory('author/skill-b', 100);
164
+ expect(historyB.length).toBe(1);
228
165
  });
229
166
  });
230
167
  });
@@ -1 +1 @@
1
- {"version":3,"file":"SkillVersionRepository.test.js","sourceRoot":"","sources":["../../tests/SkillVersionRepository.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SkillVersionRepository.test.js","sourceRoot":"","sources":["../../tests/SkillVersionRepository.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * SMI-2754: API Client Health Check Tests
3
+ *
4
+ * Tests for checkApiHealth function covering all 8 branches:
5
+ * 1. offlineMode: true → synthetic healthy, no fetch
6
+ * 2. fetch succeeds, JSON has version
7
+ * 3. fetch succeeds, JSON missing version → defaults to '1.0.0'
8
+ * 4. fetch succeeds but response.json() throws → inner catch
9
+ * 5. response.ok = false, status >= 500 → 'unhealthy'
10
+ * 6. response.ok = false, status < 500 (e.g. 429) → 'degraded'
11
+ * 7. fetch throws (network error) → outer catch → 'unhealthy'
12
+ * 8. AbortController timeout fires → 'unhealthy'
13
+ */
14
+ export {};
15
+ //# sourceMappingURL=client.health.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.health.test.d.ts","sourceRoot":"","sources":["../../../tests/api/client.health.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG"}
@@ -0,0 +1,111 @@
1
+ /**
2
+ * SMI-2754: API Client Health Check Tests
3
+ *
4
+ * Tests for checkApiHealth function covering all 8 branches:
5
+ * 1. offlineMode: true → synthetic healthy, no fetch
6
+ * 2. fetch succeeds, JSON has version
7
+ * 3. fetch succeeds, JSON missing version → defaults to '1.0.0'
8
+ * 4. fetch succeeds but response.json() throws → inner catch
9
+ * 5. response.ok = false, status >= 500 → 'unhealthy'
10
+ * 6. response.ok = false, status < 500 (e.g. 429) → 'degraded'
11
+ * 7. fetch throws (network error) → outer catch → 'unhealthy'
12
+ * 8. AbortController timeout fires → 'unhealthy'
13
+ */
14
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
15
+ import { checkApiHealth } from '../../src/api/client.health.js';
16
+ const BASE_URL = 'https://api.skillsmith.app';
17
+ const ANON_KEY = 'test-anon-key';
18
+ describe('checkApiHealth', () => {
19
+ beforeEach(() => {
20
+ vi.useFakeTimers();
21
+ });
22
+ afterEach(() => {
23
+ vi.restoreAllMocks();
24
+ vi.useRealTimers();
25
+ });
26
+ it('returns healthy immediately when offlineMode is true without calling fetch', async () => {
27
+ const fetchSpy = vi.spyOn(global, 'fetch');
28
+ const result = await checkApiHealth(BASE_URL, ANON_KEY, true);
29
+ expect(result.status).toBe('healthy');
30
+ expect(result.version).toBe('offline');
31
+ expect(typeof result.timestamp).toBe('string');
32
+ expect(fetchSpy).not.toHaveBeenCalled();
33
+ });
34
+ it('returns healthy with version from JSON when fetch succeeds', async () => {
35
+ vi.stubGlobal('fetch', vi.fn().mockResolvedValueOnce({
36
+ ok: true,
37
+ status: 200,
38
+ json: async () => ({ status: 'ok', version: '2.1.0' }),
39
+ }));
40
+ const result = await checkApiHealth(BASE_URL, ANON_KEY, false);
41
+ expect(result.status).toBe('healthy');
42
+ expect(result.version).toBe('2.1.0');
43
+ expect(typeof result.timestamp).toBe('string');
44
+ });
45
+ it('defaults version to 1.0.0 when JSON body is missing version field', async () => {
46
+ vi.stubGlobal('fetch', vi.fn().mockResolvedValueOnce({
47
+ ok: true,
48
+ status: 200,
49
+ json: async () => ({ status: 'ok' }), // no version property
50
+ }));
51
+ const result = await checkApiHealth(BASE_URL, ANON_KEY, false);
52
+ expect(result.status).toBe('healthy');
53
+ expect(result.version).toBe('1.0.0');
54
+ });
55
+ it('returns healthy with 1.0.0 when response.json() throws', async () => {
56
+ vi.stubGlobal('fetch', vi.fn().mockResolvedValueOnce({
57
+ ok: true,
58
+ status: 200,
59
+ json: async () => {
60
+ throw new SyntaxError('Unexpected token');
61
+ },
62
+ }));
63
+ const result = await checkApiHealth(BASE_URL, ANON_KEY, false);
64
+ expect(result.status).toBe('healthy');
65
+ expect(result.version).toBe('1.0.0');
66
+ });
67
+ it('returns unhealthy when response is not OK and status >= 500', async () => {
68
+ vi.stubGlobal('fetch', vi.fn().mockResolvedValueOnce({
69
+ ok: false,
70
+ status: 503,
71
+ json: async () => ({}),
72
+ }));
73
+ const result = await checkApiHealth(BASE_URL, ANON_KEY, false);
74
+ expect(result.status).toBe('unhealthy');
75
+ expect(result.version).toBe('unknown');
76
+ });
77
+ it('returns degraded when response is not OK and status < 500 (e.g. 429)', async () => {
78
+ vi.stubGlobal('fetch', vi.fn().mockResolvedValueOnce({
79
+ ok: false,
80
+ status: 429,
81
+ json: async () => ({}),
82
+ }));
83
+ const result = await checkApiHealth(BASE_URL, ANON_KEY, false);
84
+ expect(result.status).toBe('degraded');
85
+ expect(result.version).toBe('unknown');
86
+ });
87
+ it('returns unhealthy when fetch throws a network error', async () => {
88
+ vi.stubGlobal('fetch', vi.fn().mockRejectedValueOnce(new Error('Network failure')));
89
+ const result = await checkApiHealth(BASE_URL, ANON_KEY, false);
90
+ expect(result.status).toBe('unhealthy');
91
+ expect(result.version).toBe('unknown');
92
+ });
93
+ it('returns unhealthy when AbortController timeout fires before fetch resolves', async () => {
94
+ vi.stubGlobal('fetch', vi.fn().mockImplementationOnce((_url, options) => new Promise((_resolve, reject) => {
95
+ if (options?.signal) {
96
+ options.signal.addEventListener('abort', () => {
97
+ const err = new Error('The operation was aborted');
98
+ err.name = 'AbortError';
99
+ reject(err);
100
+ });
101
+ }
102
+ })));
103
+ const promise = checkApiHealth(BASE_URL, ANON_KEY, false);
104
+ // Advance past the 5000ms timeout
105
+ vi.advanceTimersByTime(6000);
106
+ const result = await promise;
107
+ expect(result.status).toBe('unhealthy');
108
+ expect(result.version).toBe('unknown');
109
+ });
110
+ });
111
+ //# sourceMappingURL=client.health.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.health.test.js","sourceRoot":"","sources":["../../../tests/api/client.health.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * SMI-2756: Wave 3 — BetterSqlite3Driver tests
3
+ *
4
+ * Tests constructor paths, WAL-mode pragma handling, execute with/without rows,
5
+ * and close paths.
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=betterSqlite3Driver.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"betterSqlite3Driver.test.d.ts","sourceRoot":"","sources":["../../../tests/db/betterSqlite3Driver.test.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}