@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
@@ -0,0 +1,50 @@
1
+ /**
2
+ * @fileoverview Update risk scorer for skill version upgrades
3
+ * @module @skillsmith/core/versioning/update-risk
4
+ * @see SMI-skill-version-tracking Wave 2
5
+ *
6
+ * Produces a RiskLevel and Recommendation for a proposed skill update
7
+ * based on change severity, risk score delta, local modification status,
8
+ * trust tier, and changelog availability.
9
+ *
10
+ * Scoring table (additive):
11
+ * change_type === 'major' → +30
12
+ * riskScoreDelta > 0 → +20
13
+ * hasLocalModifications → +20
14
+ * trustTier === 'verified' → -20
15
+ * hasChangelog → -10
16
+ *
17
+ * Buckets:
18
+ * low 0–20 → auto-update
19
+ * medium 21–40 → review-then-update
20
+ * high 41–60 → manual-review-required
21
+ * critical 61+ → manual-review-required
22
+ */
23
+ export type RiskLevel = 'low' | 'medium' | 'high' | 'critical';
24
+ export type Recommendation = 'auto-update' | 'review-then-update' | 'manual-review-required';
25
+ export interface UpdateRisk {
26
+ /** Human-readable risk bucket */
27
+ level: RiskLevel;
28
+ /** Raw additive risk score (may be negative — clamped to 0 for level mapping) */
29
+ score: number;
30
+ /** Suggested action for the caller */
31
+ recommendation: Recommendation;
32
+ }
33
+ /**
34
+ * Compute the update risk for a pending skill upgrade.
35
+ *
36
+ * @param params.changeType Semantic change type from classifyChange()
37
+ * @param params.riskScoreDelta newRiskScore - oldRiskScore (optional)
38
+ * @param params.hasLocalModifications Whether the user has edited the skill
39
+ * @param params.trustTier Registry trust tier for the skill
40
+ * @param params.hasChangelog Whether the skill includes a changelog entry
41
+ * @returns UpdateRisk with level, score, and recommendation
42
+ */
43
+ export declare function computeUpdateRisk(params: {
44
+ changeType: 'major' | 'minor' | 'patch' | 'unknown';
45
+ riskScoreDelta?: number;
46
+ hasLocalModifications: boolean;
47
+ trustTier: 'verified' | 'community' | 'experimental';
48
+ hasChangelog: boolean;
49
+ }): UpdateRisk;
50
+ //# sourceMappingURL=update-risk.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-risk.d.ts","sourceRoot":"","sources":["../../../src/versioning/update-risk.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAMH,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,CAAA;AAC9D,MAAM,MAAM,cAAc,GAAG,aAAa,GAAG,oBAAoB,GAAG,wBAAwB,CAAA;AAE5F,MAAM,WAAW,UAAU;IACzB,iCAAiC;IACjC,KAAK,EAAE,SAAS,CAAA;IAChB,iFAAiF;IACjF,KAAK,EAAE,MAAM,CAAA;IACb,sCAAsC;IACtC,cAAc,EAAE,cAAc,CAAA;CAC/B;AAgBD;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE;IACxC,UAAU,EAAE,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,SAAS,CAAA;IACnD,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,qBAAqB,EAAE,OAAO,CAAA;IAC9B,SAAS,EAAE,UAAU,GAAG,WAAW,GAAG,cAAc,CAAA;IACpD,YAAY,EAAE,OAAO,CAAA;CACtB,GAAG,UAAU,CAeb"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * @fileoverview Update risk scorer for skill version upgrades
3
+ * @module @skillsmith/core/versioning/update-risk
4
+ * @see SMI-skill-version-tracking Wave 2
5
+ *
6
+ * Produces a RiskLevel and Recommendation for a proposed skill update
7
+ * based on change severity, risk score delta, local modification status,
8
+ * trust tier, and changelog availability.
9
+ *
10
+ * Scoring table (additive):
11
+ * change_type === 'major' → +30
12
+ * riskScoreDelta > 0 → +20
13
+ * hasLocalModifications → +20
14
+ * trustTier === 'verified' → -20
15
+ * hasChangelog → -10
16
+ *
17
+ * Buckets:
18
+ * low 0–20 → auto-update
19
+ * medium 21–40 → review-then-update
20
+ * high 41–60 → manual-review-required
21
+ * critical 61+ → manual-review-required
22
+ */
23
+ // ============================================================================
24
+ // Scoring constants
25
+ // ============================================================================
26
+ const SCORE_MAJOR_CHANGE = 30;
27
+ const SCORE_RISK_DELTA_INCREASE = 20;
28
+ const SCORE_LOCAL_MODIFICATIONS = 20;
29
+ const SCORE_VERIFIED_TRUST = -20;
30
+ const SCORE_HAS_CHANGELOG = -10;
31
+ // ============================================================================
32
+ // Public API
33
+ // ============================================================================
34
+ /**
35
+ * Compute the update risk for a pending skill upgrade.
36
+ *
37
+ * @param params.changeType Semantic change type from classifyChange()
38
+ * @param params.riskScoreDelta newRiskScore - oldRiskScore (optional)
39
+ * @param params.hasLocalModifications Whether the user has edited the skill
40
+ * @param params.trustTier Registry trust tier for the skill
41
+ * @param params.hasChangelog Whether the skill includes a changelog entry
42
+ * @returns UpdateRisk with level, score, and recommendation
43
+ */
44
+ export function computeUpdateRisk(params) {
45
+ const { changeType, riskScoreDelta, hasLocalModifications, trustTier, hasChangelog } = params;
46
+ let score = 0;
47
+ if (changeType === 'major')
48
+ score += SCORE_MAJOR_CHANGE;
49
+ if (typeof riskScoreDelta === 'number' && riskScoreDelta > 0)
50
+ score += SCORE_RISK_DELTA_INCREASE;
51
+ if (hasLocalModifications)
52
+ score += SCORE_LOCAL_MODIFICATIONS;
53
+ if (trustTier === 'verified')
54
+ score += SCORE_VERIFIED_TRUST;
55
+ if (hasChangelog)
56
+ score += SCORE_HAS_CHANGELOG;
57
+ const level = scoreToLevel(score);
58
+ const recommendation = scoreToRecommendation(score);
59
+ return { level, score, recommendation };
60
+ }
61
+ // ============================================================================
62
+ // Helpers
63
+ // ============================================================================
64
+ function scoreToLevel(score) {
65
+ if (score <= 20)
66
+ return 'low';
67
+ if (score <= 40)
68
+ return 'medium';
69
+ if (score <= 60)
70
+ return 'high';
71
+ return 'critical';
72
+ }
73
+ function scoreToRecommendation(score) {
74
+ if (score <= 20)
75
+ return 'auto-update';
76
+ if (score <= 50)
77
+ return 'review-then-update';
78
+ return 'manual-review-required';
79
+ }
80
+ //# sourceMappingURL=update-risk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-risk.js","sourceRoot":"","sources":["../../../src/versioning/update-risk.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAkBH,+EAA+E;AAC/E,oBAAoB;AACpB,+EAA+E;AAE/E,MAAM,kBAAkB,GAAG,EAAE,CAAA;AAC7B,MAAM,yBAAyB,GAAG,EAAE,CAAA;AACpC,MAAM,yBAAyB,GAAG,EAAE,CAAA;AACpC,MAAM,oBAAoB,GAAG,CAAC,EAAE,CAAA;AAChC,MAAM,mBAAmB,GAAG,CAAC,EAAE,CAAA;AAE/B,+EAA+E;AAC/E,aAAa;AACb,+EAA+E;AAE/E;;;;;;;;;GASG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAMjC;IACC,MAAM,EAAE,UAAU,EAAE,cAAc,EAAE,qBAAqB,EAAE,SAAS,EAAE,YAAY,EAAE,GAAG,MAAM,CAAA;IAE7F,IAAI,KAAK,GAAG,CAAC,CAAA;IAEb,IAAI,UAAU,KAAK,OAAO;QAAE,KAAK,IAAI,kBAAkB,CAAA;IACvD,IAAI,OAAO,cAAc,KAAK,QAAQ,IAAI,cAAc,GAAG,CAAC;QAAE,KAAK,IAAI,yBAAyB,CAAA;IAChG,IAAI,qBAAqB;QAAE,KAAK,IAAI,yBAAyB,CAAA;IAC7D,IAAI,SAAS,KAAK,UAAU;QAAE,KAAK,IAAI,oBAAoB,CAAA;IAC3D,IAAI,YAAY;QAAE,KAAK,IAAI,mBAAmB,CAAA;IAE9C,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,CAAA;IACjC,MAAM,cAAc,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAA;IAEnD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,cAAc,EAAE,CAAA;AACzC,CAAC;AAED,+EAA+E;AAC/E,UAAU;AACV,+EAA+E;AAE/E,SAAS,YAAY,CAAC,KAAa;IACjC,IAAI,KAAK,IAAI,EAAE;QAAE,OAAO,KAAK,CAAA;IAC7B,IAAI,KAAK,IAAI,EAAE;QAAE,OAAO,QAAQ,CAAA;IAChC,IAAI,KAAK,IAAI,EAAE;QAAE,OAAO,MAAM,CAAA;IAC9B,OAAO,UAAU,CAAA;AACnB,CAAC;AAED,SAAS,qBAAqB,CAAC,KAAa;IAC1C,IAAI,KAAK,IAAI,EAAE;QAAE,OAAO,aAAa,CAAA;IACrC,IAAI,KAAK,IAAI,EAAE;QAAE,OAAO,oBAAoB,CAAA;IAC5C,OAAO,wBAAwB,CAAA;AACjC,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @fileoverview Tests for update-risk.ts
3
+ * @see SMI-skill-version-tracking Wave 2
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=update-risk.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-risk.test.d.ts","sourceRoot":"","sources":["../../../src/versioning/update-risk.test.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
@@ -0,0 +1,200 @@
1
+ /**
2
+ * @fileoverview Tests for update-risk.ts
3
+ * @see SMI-skill-version-tracking Wave 2
4
+ */
5
+ import { describe, it, expect } from 'vitest';
6
+ import { computeUpdateRisk } from './update-risk.js';
7
+ describe('computeUpdateRisk', () => {
8
+ describe('score → level mapping', () => {
9
+ it('returns low for score <= 20', () => {
10
+ // community, patch, no local mods, no changelog → 0
11
+ const result = computeUpdateRisk({
12
+ changeType: 'patch',
13
+ hasLocalModifications: false,
14
+ trustTier: 'community',
15
+ hasChangelog: false,
16
+ });
17
+ expect(result.level).toBe('low');
18
+ expect(result.score).toBe(0);
19
+ });
20
+ it('returns medium for score 21–40', () => {
21
+ // major (+30) + verified (-20) + changelog (-10) = 0 → low
22
+ // Let's try: major (+30) + community (0) + changelog (-10) = 20 → low
23
+ // major (+30) + community (0) + no changelog = 30 → medium
24
+ const result = computeUpdateRisk({
25
+ changeType: 'major',
26
+ hasLocalModifications: false,
27
+ trustTier: 'community',
28
+ hasChangelog: false,
29
+ });
30
+ expect(result.level).toBe('medium');
31
+ expect(result.score).toBe(30);
32
+ });
33
+ it('returns high for score 41–60', () => {
34
+ // major (30) + local mods (20) + changelog (-10) = 40 → medium
35
+ // major (30) + local mods (20) = 50 → high
36
+ const result = computeUpdateRisk({
37
+ changeType: 'major',
38
+ hasLocalModifications: true,
39
+ trustTier: 'community',
40
+ hasChangelog: false,
41
+ });
42
+ expect(result.level).toBe('high');
43
+ expect(result.score).toBe(50);
44
+ });
45
+ it('returns critical for score >= 61', () => {
46
+ // major (30) + risk delta (20) + local mods (20) = 70 → critical
47
+ const result = computeUpdateRisk({
48
+ changeType: 'major',
49
+ riskScoreDelta: 10, // positive → +20
50
+ hasLocalModifications: true,
51
+ trustTier: 'community',
52
+ hasChangelog: false,
53
+ });
54
+ expect(result.level).toBe('critical');
55
+ expect(result.score).toBe(70);
56
+ });
57
+ });
58
+ describe('score → recommendation mapping', () => {
59
+ it('returns auto-update for score <= 20', () => {
60
+ const result = computeUpdateRisk({
61
+ changeType: 'patch',
62
+ hasLocalModifications: false,
63
+ trustTier: 'community',
64
+ hasChangelog: false,
65
+ });
66
+ expect(result.recommendation).toBe('auto-update');
67
+ });
68
+ it('returns review-then-update for score 21–50', () => {
69
+ // major (30), community, no local, no changelog = 30
70
+ const result = computeUpdateRisk({
71
+ changeType: 'major',
72
+ hasLocalModifications: false,
73
+ trustTier: 'community',
74
+ hasChangelog: false,
75
+ });
76
+ expect(result.recommendation).toBe('review-then-update');
77
+ });
78
+ it('returns manual-review-required for score >= 51', () => {
79
+ // major (30) + local mods (20) = 50 → review-then-update
80
+ // major (30) + local mods (20) + risk delta (20) = 70 → manual
81
+ const result = computeUpdateRisk({
82
+ changeType: 'major',
83
+ riskScoreDelta: 5, // positive → +20
84
+ hasLocalModifications: true,
85
+ trustTier: 'community',
86
+ hasChangelog: false,
87
+ });
88
+ expect(result.recommendation).toBe('manual-review-required');
89
+ });
90
+ });
91
+ describe('individual score factors', () => {
92
+ it('verified tier reduces score by 20', () => {
93
+ const withCommunity = computeUpdateRisk({
94
+ changeType: 'patch',
95
+ hasLocalModifications: false,
96
+ trustTier: 'community',
97
+ hasChangelog: false,
98
+ });
99
+ const withVerified = computeUpdateRisk({
100
+ changeType: 'patch',
101
+ hasLocalModifications: false,
102
+ trustTier: 'verified',
103
+ hasChangelog: false,
104
+ });
105
+ expect(withVerified.score).toBe(withCommunity.score - 20);
106
+ });
107
+ it('changelog reduces score by 10', () => {
108
+ const withoutChangelog = computeUpdateRisk({
109
+ changeType: 'patch',
110
+ hasLocalModifications: false,
111
+ trustTier: 'community',
112
+ hasChangelog: false,
113
+ });
114
+ const withChangelog = computeUpdateRisk({
115
+ changeType: 'patch',
116
+ hasLocalModifications: false,
117
+ trustTier: 'community',
118
+ hasChangelog: true,
119
+ });
120
+ expect(withChangelog.score).toBe(withoutChangelog.score - 10);
121
+ });
122
+ it('hasLocalModifications adds 20', () => {
123
+ const without = computeUpdateRisk({
124
+ changeType: 'patch',
125
+ hasLocalModifications: false,
126
+ trustTier: 'community',
127
+ hasChangelog: false,
128
+ });
129
+ const with_ = computeUpdateRisk({
130
+ changeType: 'patch',
131
+ hasLocalModifications: true,
132
+ trustTier: 'community',
133
+ hasChangelog: false,
134
+ });
135
+ expect(with_.score).toBe(without.score + 20);
136
+ });
137
+ it('riskScoreDelta > 0 adds 20', () => {
138
+ const without = computeUpdateRisk({
139
+ changeType: 'patch',
140
+ riskScoreDelta: 0,
141
+ hasLocalModifications: false,
142
+ trustTier: 'community',
143
+ hasChangelog: false,
144
+ });
145
+ const with_ = computeUpdateRisk({
146
+ changeType: 'patch',
147
+ riskScoreDelta: 1, // positive
148
+ hasLocalModifications: false,
149
+ trustTier: 'community',
150
+ hasChangelog: false,
151
+ });
152
+ expect(with_.score).toBe(without.score + 20);
153
+ });
154
+ it('negative riskScoreDelta does not add penalty', () => {
155
+ const result = computeUpdateRisk({
156
+ changeType: 'patch',
157
+ riskScoreDelta: -10,
158
+ hasLocalModifications: false,
159
+ trustTier: 'community',
160
+ hasChangelog: false,
161
+ });
162
+ // risk delta ≤ 0 should not add the +20 penalty
163
+ expect(result.score).toBe(0);
164
+ });
165
+ it('undefined riskScoreDelta does not add penalty', () => {
166
+ const result = computeUpdateRisk({
167
+ changeType: 'patch',
168
+ hasLocalModifications: false,
169
+ trustTier: 'community',
170
+ hasChangelog: false,
171
+ });
172
+ expect(result.score).toBe(0);
173
+ });
174
+ });
175
+ describe('combined scenarios', () => {
176
+ it('fully safe update: patch + verified + changelog = -30 → low (clamped to 0 effectively)', () => {
177
+ const result = computeUpdateRisk({
178
+ changeType: 'patch',
179
+ hasLocalModifications: false,
180
+ trustTier: 'verified',
181
+ hasChangelog: true,
182
+ });
183
+ // 0 - 20 - 10 = -30 → level: low (score <= 20)
184
+ expect(result.level).toBe('low');
185
+ expect(result.recommendation).toBe('auto-update');
186
+ });
187
+ it('worst case scenario produces critical + manual-review-required', () => {
188
+ const result = computeUpdateRisk({
189
+ changeType: 'major',
190
+ riskScoreDelta: 50,
191
+ hasLocalModifications: true,
192
+ trustTier: 'experimental',
193
+ hasChangelog: false,
194
+ });
195
+ expect(result.level).toBe('critical');
196
+ expect(result.recommendation).toBe('manual-review-required');
197
+ });
198
+ });
199
+ });
200
+ //# sourceMappingURL=update-risk.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-risk.test.js","sourceRoot":"","sources":["../../../src/versioning/update-risk.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * SMI-2756: Wave 3 — AuditLogger edge-case tests
3
+ *
4
+ * Companion file to AuditLogger.test.ts (which exceeds the 500-line limit).
5
+ * Covers: DB write error propagation, log retention via cleanupOldLogs,
6
+ * meta-log written after successful cleanup, query date-range filters,
7
+ * query action-type filter, and export producing valid JSON.
8
+ */
9
+ export {};
10
+ //# sourceMappingURL=AuditLogger.edge-cases.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuditLogger.edge-cases.test.d.ts","sourceRoot":"","sources":["../../tests/AuditLogger.edge-cases.test.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
@@ -0,0 +1,183 @@
1
+ /**
2
+ * SMI-2756: Wave 3 — AuditLogger edge-case tests
3
+ *
4
+ * Companion file to AuditLogger.test.ts (which exceeds the 500-line limit).
5
+ * Covers: DB write error propagation, log retention via cleanupOldLogs,
6
+ * meta-log written after successful cleanup, query date-range filters,
7
+ * query action-type filter, and export producing valid JSON.
8
+ */
9
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
10
+ import { createDatabase, closeDatabase } from '../src/db/schema.js';
11
+ import { AuditLogger } from '../src/security/AuditLogger.js';
12
+ describe('AuditLogger — edge cases (SMI-2756)', () => {
13
+ let db;
14
+ let logger;
15
+ beforeEach(() => {
16
+ db = createDatabase(':memory:');
17
+ logger = new AuditLogger(db);
18
+ });
19
+ afterEach(() => {
20
+ if (db)
21
+ closeDatabase(db);
22
+ });
23
+ // -------------------------------------------------------------------------
24
+ // Retention / cleanup
25
+ // -------------------------------------------------------------------------
26
+ describe('cleanupOldLogs', () => {
27
+ it('deletes entries older than the retention period', () => {
28
+ // Insert an old log with a past timestamp
29
+ const oldTimestamp = new Date(Date.now() - 100 * 24 * 60 * 60 * 1000).toISOString();
30
+ logger.log({
31
+ event_type: 'skill_install',
32
+ actor: 'user',
33
+ resource: 'old-skill',
34
+ action: 'install',
35
+ result: 'success',
36
+ timestamp: oldTimestamp,
37
+ });
38
+ // Insert a recent log
39
+ logger.log({
40
+ event_type: 'skill_install',
41
+ actor: 'user',
42
+ resource: 'new-skill',
43
+ action: 'install',
44
+ result: 'success',
45
+ });
46
+ const deleted = logger.cleanupOldLogs(90);
47
+ // Old entry should be removed
48
+ expect(deleted).toBeGreaterThanOrEqual(1);
49
+ const remaining = logger.query({ resource: 'old-skill' });
50
+ expect(remaining).toHaveLength(0);
51
+ });
52
+ it('preserves entries within the retention period', () => {
53
+ // Insert a recent log
54
+ logger.log({
55
+ event_type: 'cache_operation',
56
+ actor: 'user',
57
+ resource: 'recent-skill',
58
+ action: 'search',
59
+ result: 'success',
60
+ });
61
+ const deleted = logger.cleanupOldLogs(90);
62
+ // No recent entries should be deleted
63
+ expect(deleted).toBe(0);
64
+ const remaining = logger.query({ resource: 'recent-skill' });
65
+ expect(remaining).toHaveLength(1);
66
+ });
67
+ it('writes a meta-log entry after successful cleanup', () => {
68
+ // Insert an old entry to be deleted
69
+ const oldTs = new Date(Date.now() - 100 * 24 * 60 * 60 * 1000).toISOString();
70
+ logger.log({
71
+ event_type: 'skill_install',
72
+ actor: 'user',
73
+ resource: 'audit_logs',
74
+ action: 'install',
75
+ result: 'success',
76
+ timestamp: oldTs,
77
+ });
78
+ logger.cleanupOldLogs(90);
79
+ // A config_change event should have been logged as meta-log
80
+ const metaEntries = logger.query({ event_type: 'config_change', resource: 'audit_logs' });
81
+ expect(metaEntries.length).toBeGreaterThanOrEqual(1);
82
+ const cleanupLog = metaEntries.find((e) => e.action === 'cleanup');
83
+ expect(cleanupLog).toBeDefined();
84
+ });
85
+ it('throws for retentionDays below minimum (< 1)', () => {
86
+ expect(() => logger.cleanupOldLogs(0)).toThrow(/minimum/);
87
+ });
88
+ it('throws for fractional retentionDays', () => {
89
+ expect(() => logger.cleanupOldLogs(1.5)).toThrow(/integer/);
90
+ });
91
+ });
92
+ // -------------------------------------------------------------------------
93
+ // Query filters
94
+ // -------------------------------------------------------------------------
95
+ describe('query — date range filters', () => {
96
+ it('filters entries by since date', () => {
97
+ const pastTs = new Date(Date.now() - 10 * 24 * 60 * 60 * 1000).toISOString();
98
+ logger.log({
99
+ event_type: 'skill_install',
100
+ actor: 'user',
101
+ resource: 'old-resource',
102
+ action: 'install',
103
+ result: 'success',
104
+ timestamp: pastTs,
105
+ });
106
+ logger.log({
107
+ event_type: 'skill_install',
108
+ actor: 'user',
109
+ resource: 'new-resource',
110
+ action: 'install',
111
+ result: 'success',
112
+ });
113
+ const since = new Date(Date.now() - 5 * 24 * 60 * 60 * 1000);
114
+ const results = logger.query({ since });
115
+ const resourceNames = results.map((e) => e.resource);
116
+ expect(resourceNames).not.toContain('old-resource');
117
+ expect(resourceNames).toContain('new-resource');
118
+ });
119
+ it('filters entries by until date', () => {
120
+ const oldTs = new Date(Date.now() - 20 * 24 * 60 * 60 * 1000).toISOString();
121
+ logger.log({
122
+ event_type: 'skill_install',
123
+ actor: 'user',
124
+ resource: 'old-resource',
125
+ action: 'install',
126
+ result: 'success',
127
+ timestamp: oldTs,
128
+ });
129
+ logger.log({
130
+ event_type: 'skill_install',
131
+ actor: 'user',
132
+ resource: 'new-resource',
133
+ action: 'install',
134
+ result: 'success',
135
+ });
136
+ const until = new Date(Date.now() - 15 * 24 * 60 * 60 * 1000);
137
+ const results = logger.query({ until });
138
+ const resourceNames = results.map((e) => e.resource);
139
+ expect(resourceNames).toContain('old-resource');
140
+ expect(resourceNames).not.toContain('new-resource');
141
+ });
142
+ });
143
+ describe('query — action type filter', () => {
144
+ it('filters by event_type', () => {
145
+ logger.log({
146
+ event_type: 'cache_operation',
147
+ actor: 'user',
148
+ resource: 'res-a',
149
+ action: 'search',
150
+ result: 'success',
151
+ });
152
+ logger.log({
153
+ event_type: 'skill_install',
154
+ actor: 'user',
155
+ resource: 'res-b',
156
+ action: 'install',
157
+ result: 'success',
158
+ });
159
+ const results = logger.query({ event_type: 'cache_operation' });
160
+ expect(results.every((e) => e.event_type === 'cache_operation')).toBe(true);
161
+ expect(results.some((e) => e.resource === 'res-a')).toBe(true);
162
+ });
163
+ });
164
+ // -------------------------------------------------------------------------
165
+ // export
166
+ // -------------------------------------------------------------------------
167
+ describe('export', () => {
168
+ it('returns valid JSON string containing logged entries', () => {
169
+ logger.log({
170
+ event_type: 'cache_operation',
171
+ actor: 'user',
172
+ resource: 'exported-resource',
173
+ action: 'search',
174
+ result: 'success',
175
+ });
176
+ const json = logger.export();
177
+ const parsed = JSON.parse(json);
178
+ expect(Array.isArray(parsed)).toBe(true);
179
+ expect(parsed.some((e) => e.resource === 'exported-resource')).toBe(true);
180
+ });
181
+ });
182
+ });
183
+ //# sourceMappingURL=AuditLogger.edge-cases.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuditLogger.edge-cases.test.js","sourceRoot":"","sources":["../../tests/AuditLogger.edge-cases.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * SMI-2756: Wave 3 — CacheManager tests
3
+ *
4
+ * CacheManager uses an async factory pattern (CacheManager.create(config)).
5
+ * Tests cover: create/close lifecycle, get/set/has/delete, invalidateAll,
6
+ * onInvalidate listener, getStats shape, and generateKey/parseKey symmetry.
7
+ */
8
+ export {};
9
+ //# sourceMappingURL=CacheManager.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CacheManager.test.d.ts","sourceRoot":"","sources":["../../tests/CacheManager.test.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}