@skillsmith/core 0.1.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (325) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/src/analysis/CodebaseAnalyzer.d.ts +4 -134
  3. package/dist/src/analysis/CodebaseAnalyzer.d.ts.map +1 -1
  4. package/dist/src/analysis/CodebaseAnalyzer.js +7 -315
  5. package/dist/src/analysis/CodebaseAnalyzer.js.map +1 -1
  6. package/dist/src/analysis/framework-detector.d.ts +47 -0
  7. package/dist/src/analysis/framework-detector.d.ts.map +1 -0
  8. package/dist/src/analysis/framework-detector.js +151 -0
  9. package/dist/src/analysis/framework-detector.js.map +1 -0
  10. package/dist/src/analysis/index.d.ts +6 -1
  11. package/dist/src/analysis/index.d.ts.map +1 -1
  12. package/dist/src/analysis/index.js +10 -1
  13. package/dist/src/analysis/index.js.map +1 -1
  14. package/dist/src/analysis/parsers.d.ts +43 -0
  15. package/dist/src/analysis/parsers.d.ts.map +1 -0
  16. package/dist/src/analysis/parsers.js +219 -0
  17. package/dist/src/analysis/parsers.js.map +1 -0
  18. package/dist/src/analysis/types.d.ts +138 -0
  19. package/dist/src/analysis/types.d.ts.map +1 -0
  20. package/dist/src/analysis/types.js +25 -0
  21. package/dist/src/analysis/types.js.map +1 -0
  22. package/dist/src/analytics/AnalyticsRepository.d.ts.map +1 -1
  23. package/dist/src/analytics/AnalyticsRepository.js +4 -4
  24. package/dist/src/analytics/AnalyticsRepository.js.map +1 -1
  25. package/dist/src/api/cache.d.ts +108 -0
  26. package/dist/src/api/cache.d.ts.map +1 -0
  27. package/dist/src/api/cache.js +216 -0
  28. package/dist/src/api/cache.js.map +1 -0
  29. package/dist/src/api/client.d.ts +152 -0
  30. package/dist/src/api/client.d.ts.map +1 -0
  31. package/dist/src/api/client.js +221 -0
  32. package/dist/src/api/client.js.map +1 -0
  33. package/dist/src/api/index.d.ts +10 -0
  34. package/dist/src/api/index.d.ts.map +1 -0
  35. package/dist/src/api/index.js +10 -0
  36. package/dist/src/api/index.js.map +1 -0
  37. package/dist/src/benchmarks/BenchmarkRunner.d.ts +6 -175
  38. package/dist/src/benchmarks/BenchmarkRunner.d.ts.map +1 -1
  39. package/dist/src/benchmarks/BenchmarkRunner.js +6 -123
  40. package/dist/src/benchmarks/BenchmarkRunner.js.map +1 -1
  41. package/dist/src/benchmarks/MemoryProfiler.d.ts +4 -262
  42. package/dist/src/benchmarks/MemoryProfiler.d.ts.map +1 -1
  43. package/dist/src/benchmarks/MemoryProfiler.js +4 -400
  44. package/dist/src/benchmarks/MemoryProfiler.js.map +1 -1
  45. package/dist/src/benchmarks/comparator.d.ts +38 -0
  46. package/dist/src/benchmarks/comparator.d.ts.map +1 -0
  47. package/dist/src/benchmarks/comparator.js +81 -0
  48. package/dist/src/benchmarks/comparator.js.map +1 -0
  49. package/dist/src/benchmarks/formatters.d.ts +30 -0
  50. package/dist/src/benchmarks/formatters.d.ts.map +1 -0
  51. package/dist/src/benchmarks/formatters.js +88 -0
  52. package/dist/src/benchmarks/formatters.js.map +1 -0
  53. package/dist/src/benchmarks/index.d.ts +5 -1
  54. package/dist/src/benchmarks/index.d.ts.map +1 -1
  55. package/dist/src/benchmarks/index.js +9 -2
  56. package/dist/src/benchmarks/index.js.map +1 -1
  57. package/dist/src/benchmarks/memory/MemoryProfiler.d.ts +165 -0
  58. package/dist/src/benchmarks/memory/MemoryProfiler.d.ts.map +1 -0
  59. package/dist/src/benchmarks/memory/MemoryProfiler.js +312 -0
  60. package/dist/src/benchmarks/memory/MemoryProfiler.js.map +1 -0
  61. package/dist/src/benchmarks/memory/baseline-manager.d.ts +64 -0
  62. package/dist/src/benchmarks/memory/baseline-manager.d.ts.map +1 -0
  63. package/dist/src/benchmarks/memory/baseline-manager.js +95 -0
  64. package/dist/src/benchmarks/memory/baseline-manager.js.map +1 -0
  65. package/dist/src/benchmarks/memory/index.d.ts +12 -0
  66. package/dist/src/benchmarks/memory/index.d.ts.map +1 -0
  67. package/dist/src/benchmarks/memory/index.js +12 -0
  68. package/dist/src/benchmarks/memory/index.js.map +1 -0
  69. package/dist/src/benchmarks/memory/leak-detector.d.ts +23 -0
  70. package/dist/src/benchmarks/memory/leak-detector.d.ts.map +1 -0
  71. package/dist/src/benchmarks/memory/leak-detector.js +46 -0
  72. package/dist/src/benchmarks/memory/leak-detector.js.map +1 -0
  73. package/dist/src/benchmarks/memory/regression-detector.d.ts +17 -0
  74. package/dist/src/benchmarks/memory/regression-detector.d.ts.map +1 -0
  75. package/dist/src/benchmarks/memory/regression-detector.js +56 -0
  76. package/dist/src/benchmarks/memory/regression-detector.js.map +1 -0
  77. package/dist/src/benchmarks/memory/types.d.ts +111 -0
  78. package/dist/src/benchmarks/memory/types.d.ts.map +1 -0
  79. package/dist/src/benchmarks/memory/types.js +7 -0
  80. package/dist/src/benchmarks/memory/types.js.map +1 -0
  81. package/dist/src/benchmarks/memory/utils.d.ts +17 -0
  82. package/dist/src/benchmarks/memory/utils.d.ts.map +1 -0
  83. package/dist/src/benchmarks/memory/utils.js +29 -0
  84. package/dist/src/benchmarks/memory/utils.js.map +1 -0
  85. package/dist/src/benchmarks/types.d.ts +175 -0
  86. package/dist/src/benchmarks/types.d.ts.map +1 -0
  87. package/dist/src/benchmarks/types.js +20 -0
  88. package/dist/src/benchmarks/types.js.map +1 -0
  89. package/dist/src/index.d.ts +4 -2
  90. package/dist/src/index.d.ts.map +1 -1
  91. package/dist/src/index.js +7 -3
  92. package/dist/src/index.js.map +1 -1
  93. package/dist/src/repositories/QuarantineRepository.d.ts +4 -251
  94. package/dist/src/repositories/QuarantineRepository.d.ts.map +1 -1
  95. package/dist/src/repositories/QuarantineRepository.js +4 -441
  96. package/dist/src/repositories/QuarantineRepository.js.map +1 -1
  97. package/dist/src/repositories/quarantine/QuarantineRepository.d.ts +168 -0
  98. package/dist/src/repositories/quarantine/QuarantineRepository.d.ts.map +1 -0
  99. package/dist/src/repositories/quarantine/QuarantineRepository.js +341 -0
  100. package/dist/src/repositories/quarantine/QuarantineRepository.js.map +1 -0
  101. package/dist/src/repositories/quarantine/index.d.ts +10 -0
  102. package/dist/src/repositories/quarantine/index.d.ts.map +1 -0
  103. package/dist/src/repositories/quarantine/index.js +10 -0
  104. package/dist/src/repositories/quarantine/index.js.map +1 -0
  105. package/dist/src/repositories/quarantine/queries.d.ts +58 -0
  106. package/dist/src/repositories/quarantine/queries.d.ts.map +1 -0
  107. package/dist/src/repositories/quarantine/queries.js +88 -0
  108. package/dist/src/repositories/quarantine/queries.js.map +1 -0
  109. package/dist/src/repositories/quarantine/query-builder.d.ts +44 -0
  110. package/dist/src/repositories/quarantine/query-builder.d.ts.map +1 -0
  111. package/dist/src/repositories/quarantine/query-builder.js +87 -0
  112. package/dist/src/repositories/quarantine/query-builder.js.map +1 -0
  113. package/dist/src/repositories/quarantine/types.d.ts +155 -0
  114. package/dist/src/repositories/quarantine/types.d.ts.map +1 -0
  115. package/dist/src/repositories/quarantine/types.js +13 -0
  116. package/dist/src/repositories/quarantine/types.js.map +1 -0
  117. package/dist/src/scripts/__tests__/scan-imported-skills.test.d.ts +1 -0
  118. package/dist/src/scripts/__tests__/scan-imported-skills.test.d.ts.map +1 -1
  119. package/dist/src/scripts/__tests__/scan-imported-skills.test.js +7 -43
  120. package/dist/src/scripts/__tests__/scan-imported-skills.test.js.map +1 -1
  121. package/dist/src/scripts/github-import/checkpoint.d.ts +21 -0
  122. package/dist/src/scripts/github-import/checkpoint.d.ts.map +1 -0
  123. package/dist/src/scripts/github-import/checkpoint.js +52 -0
  124. package/dist/src/scripts/github-import/checkpoint.js.map +1 -0
  125. package/dist/src/scripts/github-import/deduplication.d.ts +15 -0
  126. package/dist/src/scripts/github-import/deduplication.d.ts.map +1 -0
  127. package/dist/src/scripts/github-import/deduplication.js +33 -0
  128. package/dist/src/scripts/github-import/deduplication.js.map +1 -0
  129. package/dist/src/scripts/github-import/github-client.d.ts +29 -0
  130. package/dist/src/scripts/github-import/github-client.d.ts.map +1 -0
  131. package/dist/src/scripts/github-import/github-client.js +184 -0
  132. package/dist/src/scripts/github-import/github-client.js.map +1 -0
  133. package/dist/src/scripts/github-import/index.d.ts +29 -0
  134. package/dist/src/scripts/github-import/index.d.ts.map +1 -0
  135. package/dist/src/scripts/github-import/index.js +198 -0
  136. package/dist/src/scripts/github-import/index.js.map +1 -0
  137. package/dist/src/scripts/github-import/output.d.ts +12 -0
  138. package/dist/src/scripts/github-import/output.d.ts.map +1 -0
  139. package/dist/src/scripts/github-import/output.js +34 -0
  140. package/dist/src/scripts/github-import/output.js.map +1 -0
  141. package/dist/src/scripts/github-import/types.d.ts +108 -0
  142. package/dist/src/scripts/github-import/types.d.ts.map +1 -0
  143. package/dist/src/scripts/github-import/types.js +44 -0
  144. package/dist/src/scripts/github-import/types.js.map +1 -0
  145. package/dist/src/scripts/github-import/utils.d.ts +13 -0
  146. package/dist/src/scripts/github-import/utils.d.ts.map +1 -0
  147. package/dist/src/scripts/github-import/utils.js +28 -0
  148. package/dist/src/scripts/github-import/utils.js.map +1 -0
  149. package/dist/src/scripts/import-github-skills.d.ts +3 -12
  150. package/dist/src/scripts/import-github-skills.d.ts.map +1 -1
  151. package/dist/src/scripts/import-github-skills.js +18 -398
  152. package/dist/src/scripts/import-github-skills.js.map +1 -1
  153. package/dist/src/scripts/scan-imported-skills.d.ts +7 -7
  154. package/dist/src/scripts/scan-imported-skills.d.ts.map +1 -1
  155. package/dist/src/scripts/scan-imported-skills.js +8 -397
  156. package/dist/src/scripts/scan-imported-skills.js.map +1 -1
  157. package/dist/src/scripts/skill-scanner/categorizer.d.ts +43 -0
  158. package/dist/src/scripts/skill-scanner/categorizer.d.ts.map +1 -0
  159. package/dist/src/scripts/skill-scanner/categorizer.js +61 -0
  160. package/dist/src/scripts/skill-scanner/categorizer.js.map +1 -0
  161. package/dist/src/scripts/skill-scanner/file-scanner.d.ts +43 -0
  162. package/dist/src/scripts/skill-scanner/file-scanner.d.ts.map +1 -0
  163. package/dist/src/scripts/skill-scanner/file-scanner.js +90 -0
  164. package/dist/src/scripts/skill-scanner/file-scanner.js.map +1 -0
  165. package/dist/src/scripts/skill-scanner/index.d.ts +22 -0
  166. package/dist/src/scripts/skill-scanner/index.d.ts.map +1 -0
  167. package/dist/src/scripts/skill-scanner/index.js +43 -0
  168. package/dist/src/scripts/skill-scanner/index.js.map +1 -0
  169. package/dist/src/scripts/skill-scanner/logger.d.ts +59 -0
  170. package/dist/src/scripts/skill-scanner/logger.d.ts.map +1 -0
  171. package/dist/src/scripts/skill-scanner/logger.js +104 -0
  172. package/dist/src/scripts/skill-scanner/logger.js.map +1 -0
  173. package/dist/src/scripts/skill-scanner/reporter.d.ts +56 -0
  174. package/dist/src/scripts/skill-scanner/reporter.d.ts.map +1 -0
  175. package/dist/src/scripts/skill-scanner/reporter.js +166 -0
  176. package/dist/src/scripts/skill-scanner/reporter.js.map +1 -0
  177. package/dist/src/scripts/skill-scanner/scanner.d.ts +44 -0
  178. package/dist/src/scripts/skill-scanner/scanner.d.ts.map +1 -0
  179. package/dist/src/scripts/skill-scanner/scanner.js +140 -0
  180. package/dist/src/scripts/skill-scanner/scanner.js.map +1 -0
  181. package/dist/src/scripts/skill-scanner/trust-scorer.d.ts +59 -0
  182. package/dist/src/scripts/skill-scanner/trust-scorer.d.ts.map +1 -0
  183. package/dist/src/scripts/skill-scanner/trust-scorer.js +62 -0
  184. package/dist/src/scripts/skill-scanner/trust-scorer.js.map +1 -0
  185. package/dist/src/scripts/skill-scanner/types.d.ts +98 -0
  186. package/dist/src/scripts/skill-scanner/types.d.ts.map +1 -0
  187. package/dist/src/scripts/skill-scanner/types.js +7 -0
  188. package/dist/src/scripts/skill-scanner/types.js.map +1 -0
  189. package/dist/src/scripts/validate-skills.d.ts +3 -172
  190. package/dist/src/scripts/validate-skills.d.ts.map +1 -1
  191. package/dist/src/scripts/validate-skills.js +6 -519
  192. package/dist/src/scripts/validate-skills.js.map +1 -1
  193. package/dist/src/scripts/validation/deduplication.d.ts +23 -0
  194. package/dist/src/scripts/validation/deduplication.d.ts.map +1 -0
  195. package/dist/src/scripts/validation/deduplication.js +127 -0
  196. package/dist/src/scripts/validation/deduplication.js.map +1 -0
  197. package/dist/src/scripts/validation/field-validators.d.ts +9 -0
  198. package/dist/src/scripts/validation/field-validators.d.ts.map +1 -0
  199. package/dist/src/scripts/validation/field-validators.js +135 -0
  200. package/dist/src/scripts/validation/field-validators.js.map +1 -0
  201. package/dist/src/scripts/validation/index.d.ts +29 -0
  202. package/dist/src/scripts/validation/index.d.ts.map +1 -0
  203. package/dist/src/scripts/validation/index.js +84 -0
  204. package/dist/src/scripts/validation/index.js.map +1 -0
  205. package/dist/src/scripts/validation/normalizers.d.ts +29 -0
  206. package/dist/src/scripts/validation/normalizers.d.ts.map +1 -0
  207. package/dist/src/scripts/validation/normalizers.js +79 -0
  208. package/dist/src/scripts/validation/normalizers.js.map +1 -0
  209. package/dist/src/scripts/validation/pipeline.d.ts +13 -0
  210. package/dist/src/scripts/validation/pipeline.d.ts.map +1 -0
  211. package/dist/src/scripts/validation/pipeline.js +126 -0
  212. package/dist/src/scripts/validation/pipeline.js.map +1 -0
  213. package/dist/src/scripts/validation/types.d.ts +128 -0
  214. package/dist/src/scripts/validation/types.d.ts.map +1 -0
  215. package/dist/src/scripts/validation/types.js +43 -0
  216. package/dist/src/scripts/validation/types.js.map +1 -0
  217. package/dist/src/security/index.d.ts +5 -4
  218. package/dist/src/security/index.d.ts.map +1 -1
  219. package/dist/src/security/index.js +8 -2
  220. package/dist/src/security/index.js.map +1 -1
  221. package/dist/src/security/rate-limiter/RateLimiter.d.ts +86 -0
  222. package/dist/src/security/rate-limiter/RateLimiter.d.ts.map +1 -0
  223. package/dist/src/security/rate-limiter/RateLimiter.js +260 -0
  224. package/dist/src/security/rate-limiter/RateLimiter.js.map +1 -0
  225. package/dist/src/security/rate-limiter/constants.d.ts +15 -0
  226. package/dist/src/security/rate-limiter/constants.d.ts.map +1 -0
  227. package/dist/src/security/rate-limiter/constants.js +15 -0
  228. package/dist/src/security/rate-limiter/constants.js.map +1 -0
  229. package/dist/src/security/rate-limiter/errors.d.ts +22 -0
  230. package/dist/src/security/rate-limiter/errors.d.ts.map +1 -0
  231. package/dist/src/security/rate-limiter/errors.js +32 -0
  232. package/dist/src/security/rate-limiter/errors.js.map +1 -0
  233. package/dist/src/security/rate-limiter/index.d.ts +12 -0
  234. package/dist/src/security/rate-limiter/index.d.ts.map +1 -0
  235. package/dist/src/security/rate-limiter/index.js +16 -0
  236. package/dist/src/security/rate-limiter/index.js.map +1 -0
  237. package/dist/src/security/rate-limiter/metrics-manager.d.ts +55 -0
  238. package/dist/src/security/rate-limiter/metrics-manager.d.ts.map +1 -0
  239. package/dist/src/security/rate-limiter/metrics-manager.js +144 -0
  240. package/dist/src/security/rate-limiter/metrics-manager.js.map +1 -0
  241. package/dist/src/security/rate-limiter/presets.d.ts +52 -0
  242. package/dist/src/security/rate-limiter/presets.d.ts.map +1 -0
  243. package/dist/src/security/rate-limiter/presets.js +53 -0
  244. package/dist/src/security/rate-limiter/presets.js.map +1 -0
  245. package/dist/src/security/rate-limiter/queue-manager.d.ts +59 -0
  246. package/dist/src/security/rate-limiter/queue-manager.d.ts.map +1 -0
  247. package/dist/src/security/rate-limiter/queue-manager.js +189 -0
  248. package/dist/src/security/rate-limiter/queue-manager.js.map +1 -0
  249. package/dist/src/security/rate-limiter/storage.d.ts +34 -0
  250. package/dist/src/security/rate-limiter/storage.d.ts.map +1 -0
  251. package/dist/src/security/rate-limiter/storage.js +80 -0
  252. package/dist/src/security/rate-limiter/storage.js.map +1 -0
  253. package/dist/src/security/rate-limiter/token-bucket.d.ts +44 -0
  254. package/dist/src/security/rate-limiter/token-bucket.d.ts.map +1 -0
  255. package/dist/src/security/rate-limiter/token-bucket.js +99 -0
  256. package/dist/src/security/rate-limiter/token-bucket.js.map +1 -0
  257. package/dist/src/security/rate-limiter/types.d.ts +104 -0
  258. package/dist/src/security/rate-limiter/types.d.ts.map +1 -0
  259. package/dist/src/security/rate-limiter/types.js +7 -0
  260. package/dist/src/security/rate-limiter/types.js.map +1 -0
  261. package/dist/src/security/scanner/SecurityScanner.d.ts +94 -0
  262. package/dist/src/security/scanner/SecurityScanner.d.ts.map +1 -0
  263. package/dist/src/security/scanner/SecurityScanner.js +403 -0
  264. package/dist/src/security/scanner/SecurityScanner.js.map +1 -0
  265. package/dist/src/security/scanner/index.d.ts +11 -0
  266. package/dist/src/security/scanner/index.d.ts.map +1 -0
  267. package/dist/src/security/scanner/index.js +14 -0
  268. package/dist/src/security/scanner/index.js.map +1 -0
  269. package/dist/src/security/scanner/patterns.d.ts +14 -0
  270. package/dist/src/security/scanner/patterns.d.ts.map +1 -0
  271. package/dist/src/security/scanner/patterns.js +147 -0
  272. package/dist/src/security/scanner/patterns.js.map +1 -0
  273. package/dist/src/security/scanner/regex-utils.d.ts +33 -0
  274. package/dist/src/security/scanner/regex-utils.d.ts.map +1 -0
  275. package/dist/src/security/scanner/regex-utils.js +41 -0
  276. package/dist/src/security/scanner/regex-utils.js.map +1 -0
  277. package/dist/src/security/scanner/types.d.ts +63 -0
  278. package/dist/src/security/scanner/types.d.ts.map +1 -0
  279. package/dist/src/security/scanner/types.js +7 -0
  280. package/dist/src/security/scanner/types.js.map +1 -0
  281. package/dist/src/security/scanner/weights.d.ts +15 -0
  282. package/dist/src/security/scanner/weights.d.ts.map +1 -0
  283. package/dist/src/security/scanner/weights.js +28 -0
  284. package/dist/src/security/scanner/weights.js.map +1 -0
  285. package/dist/src/session/SessionHealthMonitor.d.ts +5 -168
  286. package/dist/src/session/SessionHealthMonitor.d.ts.map +1 -1
  287. package/dist/src/session/SessionHealthMonitor.js +22 -91
  288. package/dist/src/session/SessionHealthMonitor.js.map +1 -1
  289. package/dist/src/session/health-checks.d.ts +37 -0
  290. package/dist/src/session/health-checks.d.ts.map +1 -0
  291. package/dist/src/session/health-checks.js +64 -0
  292. package/dist/src/session/health-checks.js.map +1 -0
  293. package/dist/src/session/health-types.d.ts +78 -0
  294. package/dist/src/session/health-types.d.ts.map +1 -0
  295. package/dist/src/session/health-types.js +16 -0
  296. package/dist/src/session/health-types.js.map +1 -0
  297. package/dist/src/session/index.d.ts +5 -1
  298. package/dist/src/session/index.d.ts.map +1 -1
  299. package/dist/src/session/index.js +9 -0
  300. package/dist/src/session/index.js.map +1 -1
  301. package/dist/src/session/metrics-collector.d.ts +23 -0
  302. package/dist/src/session/metrics-collector.d.ts.map +1 -0
  303. package/dist/src/session/metrics-collector.js +44 -0
  304. package/dist/src/session/metrics-collector.js.map +1 -0
  305. package/dist/src/session/typed-event-emitter.d.ts +70 -0
  306. package/dist/src/session/typed-event-emitter.d.ts.map +1 -0
  307. package/dist/src/session/typed-event-emitter.js +79 -0
  308. package/dist/src/session/typed-event-emitter.js.map +1 -0
  309. package/dist/src/sources/BaseSourceAdapter.d.ts +1 -1
  310. package/dist/src/sources/BaseSourceAdapter.d.ts.map +1 -1
  311. package/dist/src/sources/BaseSourceAdapter.js +2 -2
  312. package/dist/src/sources/BaseSourceAdapter.js.map +1 -1
  313. package/dist/src/telemetry/index.d.ts +1 -0
  314. package/dist/src/telemetry/index.d.ts.map +1 -1
  315. package/dist/src/telemetry/index.js +2 -0
  316. package/dist/src/telemetry/index.js.map +1 -1
  317. package/dist/src/telemetry/posthog.d.ts +125 -0
  318. package/dist/src/telemetry/posthog.d.ts.map +1 -0
  319. package/dist/src/telemetry/posthog.js +198 -0
  320. package/dist/src/telemetry/posthog.js.map +1 -0
  321. package/dist/tests/RateLimiter.test.js +4 -4
  322. package/dist/tests/RateLimiter.test.js.map +1 -1
  323. package/dist/tests/e2e/security/security.e2e.test.js +3 -3
  324. package/dist/tests/e2e/security/security.e2e.test.js.map +1 -1
  325. package/package.json +2 -1
@@ -0,0 +1,127 @@
1
+ /**
2
+ * SMI-863: Deduplication functions for skill validation
3
+ */
4
+ import { EmbeddingService } from '../../embeddings/index.js';
5
+ import { CONFIG } from './types.js';
6
+ import { hashRepoUrl } from './normalizers.js';
7
+ /**
8
+ * Compare two skills and determine which to keep based on source priority and quality
9
+ */
10
+ export function compareSkillsForDedup(a, b) {
11
+ const priorityA = CONFIG.SOURCE_PRIORITY[a.source] ?? CONFIG.SOURCE_PRIORITY.unknown;
12
+ const priorityB = CONFIG.SOURCE_PRIORITY[b.source] ?? CONFIG.SOURCE_PRIORITY.unknown;
13
+ // Higher source priority wins
14
+ if (priorityA !== priorityB) {
15
+ return priorityA > priorityB ? 'a' : 'b';
16
+ }
17
+ // Same source priority - higher quality score wins
18
+ return a.quality_score >= b.quality_score ? 'a' : 'b';
19
+ }
20
+ /**
21
+ * Deduplicate skills by repo_url
22
+ */
23
+ export function deduplicateByRepoUrl(skills) {
24
+ const seen = new Map();
25
+ const duplicates = [];
26
+ for (const skill of skills) {
27
+ if (!skill.repo_url) {
28
+ // Skills without repo_url are kept (will be checked for semantic similarity)
29
+ // Use ID as key for skills without repo_url
30
+ const key = `no-url:${skill.id}`;
31
+ if (!seen.has(key)) {
32
+ seen.set(key, skill);
33
+ }
34
+ continue;
35
+ }
36
+ const key = hashRepoUrl(skill.repo_url);
37
+ const existing = seen.get(key);
38
+ if (existing) {
39
+ const winner = compareSkillsForDedup(existing, skill);
40
+ if (winner === 'b') {
41
+ duplicates.push({
42
+ kept: skill,
43
+ discarded: existing,
44
+ reason: 'repo_url',
45
+ });
46
+ seen.set(key, skill);
47
+ }
48
+ else {
49
+ duplicates.push({
50
+ kept: existing,
51
+ discarded: skill,
52
+ reason: 'repo_url',
53
+ });
54
+ }
55
+ }
56
+ else {
57
+ seen.set(key, skill);
58
+ }
59
+ }
60
+ return {
61
+ unique: Array.from(seen.values()),
62
+ duplicates,
63
+ };
64
+ }
65
+ /**
66
+ * Detect semantic duplicates using embedding similarity
67
+ */
68
+ export async function detectSemanticDuplicates(skills, threshold = CONFIG.SIMILARITY_THRESHOLD) {
69
+ if (skills.length === 0) {
70
+ return { unique: [], duplicates: [] };
71
+ }
72
+ // Use fallback mode for faster processing
73
+ const embeddingService = new EmbeddingService({ useFallback: true });
74
+ const duplicates = [];
75
+ const unique = [];
76
+ const embeddings = new Map();
77
+ try {
78
+ // Generate embeddings for all skills
79
+ for (const skill of skills) {
80
+ const text = `${skill.name} ${skill.description}`;
81
+ const embedding = await embeddingService.embed(text);
82
+ embeddings.set(skill.id, embedding);
83
+ }
84
+ // Check each skill against accepted unique skills
85
+ for (const skill of skills) {
86
+ const skillEmbedding = embeddings.get(skill.id);
87
+ let isDuplicate = false;
88
+ for (const uniqueSkill of unique) {
89
+ const uniqueEmbedding = embeddings.get(uniqueSkill.id);
90
+ const similarity = embeddingService.cosineSimilarity(skillEmbedding, uniqueEmbedding);
91
+ if (similarity >= threshold) {
92
+ // Found semantic duplicate
93
+ const winner = compareSkillsForDedup(uniqueSkill, skill);
94
+ if (winner === 'b') {
95
+ // New skill is better - swap
96
+ const index = unique.indexOf(uniqueSkill);
97
+ unique[index] = skill;
98
+ duplicates.push({
99
+ kept: skill,
100
+ discarded: uniqueSkill,
101
+ reason: 'semantic_similarity',
102
+ similarity,
103
+ });
104
+ }
105
+ else {
106
+ duplicates.push({
107
+ kept: uniqueSkill,
108
+ discarded: skill,
109
+ reason: 'semantic_similarity',
110
+ similarity,
111
+ });
112
+ }
113
+ isDuplicate = true;
114
+ break;
115
+ }
116
+ }
117
+ if (!isDuplicate) {
118
+ unique.push(skill);
119
+ }
120
+ }
121
+ }
122
+ finally {
123
+ embeddingService.close();
124
+ }
125
+ return { unique, duplicates };
126
+ }
127
+ //# sourceMappingURL=deduplication.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deduplication.js","sourceRoot":"","sources":["../../../../src/scripts/validation/deduplication.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * SMI-863: Field validation functions for individual skill fields
3
+ */
4
+ import { RawSkillInput, SkillValidationResult } from './types.js';
5
+ /**
6
+ * Validate a single skill and apply auto-fixes where possible
7
+ */
8
+ export declare function validateSkill(raw: RawSkillInput): SkillValidationResult;
9
+ //# sourceMappingURL=field-validators.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"field-validators.d.ts","sourceRoot":"","sources":["../../../../src/scripts/validation/field-validators.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAGL,aAAa,EAGb,qBAAqB,EACtB,MAAM,YAAY,CAAA;AASnB;;GAEG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,aAAa,GAAG,qBAAqB,CAuIvE"}
@@ -0,0 +1,135 @@
1
+ /**
2
+ * SMI-863: Field validation functions for individual skill fields
3
+ */
4
+ import { CONFIG, } from './types.js';
5
+ import { extractOwnerFromRepoUrl, generateSkillId, normalizeQualityScore, normalizeTrustTier, normalizeSource, } from './normalizers.js';
6
+ /**
7
+ * Validate a single skill and apply auto-fixes where possible
8
+ */
9
+ export function validateSkill(raw) {
10
+ const errors = [];
11
+ const warnings = [];
12
+ const fixes = [];
13
+ // Normalize field names (handle both snake_case and camelCase)
14
+ const repoUrl = raw.repo_url ?? raw.repoUrl ?? null;
15
+ const qualityScore = raw.quality_score ?? raw.qualityScore ?? null;
16
+ const trustTier = raw.trust_tier ?? raw.trustTier ?? null;
17
+ // 1. Validate name (required)
18
+ const name = raw.name?.trim() || '';
19
+ if (!name) {
20
+ errors.push({ field: 'name', message: 'Name is required and cannot be empty' });
21
+ }
22
+ // 2. Validate author (use repo owner if missing)
23
+ let author = raw.author?.trim() || '';
24
+ if (!author) {
25
+ const ownerFromUrl = extractOwnerFromRepoUrl(repoUrl);
26
+ if (ownerFromUrl) {
27
+ author = ownerFromUrl;
28
+ fixes.push(`Auto-filled author from repo URL: "${author}"`);
29
+ }
30
+ else {
31
+ errors.push({
32
+ field: 'author',
33
+ message: 'Author is required (could not extract from repo URL)',
34
+ });
35
+ }
36
+ }
37
+ // 3. Validate description (use first 100 chars of name if missing)
38
+ let description = raw.description?.trim() || '';
39
+ if (!description) {
40
+ if (name) {
41
+ description = name.length > 100 ? name.substring(0, 100) + '...' : name;
42
+ fixes.push(`Auto-filled description from name: "${description}"`);
43
+ }
44
+ else {
45
+ errors.push({ field: 'description', message: 'Description is required' });
46
+ }
47
+ }
48
+ // 4. Validate ID format (author/name)
49
+ let id = raw.id?.trim() || '';
50
+ if (!id && author && name) {
51
+ id = generateSkillId(author, name);
52
+ fixes.push(`Auto-generated ID: "${id}"`);
53
+ }
54
+ if (id && !id.match(/^[^/]+\/[^/]+$/)) {
55
+ if (author && name) {
56
+ const newId = generateSkillId(author, name);
57
+ fixes.push(`Fixed invalid ID format: "${id}" -> "${newId}"`);
58
+ id = newId;
59
+ }
60
+ else {
61
+ errors.push({
62
+ field: 'id',
63
+ message: 'ID must be in format author/name',
64
+ value: id,
65
+ });
66
+ }
67
+ }
68
+ // 5. Validate quality score (0-100)
69
+ const normalizedScore = normalizeQualityScore(qualityScore);
70
+ if (qualityScore !== null && qualityScore !== undefined) {
71
+ if (qualityScore < 0 || qualityScore > 100) {
72
+ if (qualityScore >= 0 && qualityScore <= 1) {
73
+ fixes.push(`Normalized quality score from 0-1 to 0-100: ${qualityScore} -> ${normalizedScore}`);
74
+ }
75
+ else {
76
+ fixes.push(`Clamped quality score to 0-100: ${qualityScore} -> ${normalizedScore}`);
77
+ }
78
+ }
79
+ }
80
+ else {
81
+ warnings.push('Quality score missing, defaulted to 50');
82
+ }
83
+ // 6. Validate trust tier (enum)
84
+ const normalizedTrustTier = normalizeTrustTier(trustTier);
85
+ if (trustTier && !CONFIG.VALID_TRUST_TIERS.includes(trustTier)) {
86
+ fixes.push(`Normalized trust tier: "${trustTier}" -> "${normalizedTrustTier}"`);
87
+ }
88
+ // Validate source
89
+ const source = normalizeSource(raw.source);
90
+ if (!raw.source) {
91
+ warnings.push('Source missing, defaulted to "unknown"');
92
+ }
93
+ // Validate tags
94
+ const tags = Array.isArray(raw.tags) ? raw.tags.filter((t) => typeof t === 'string') : [];
95
+ // Check repo_url format if present
96
+ if (repoUrl) {
97
+ try {
98
+ new URL(repoUrl);
99
+ }
100
+ catch {
101
+ warnings.push(`Invalid repo URL format: "${repoUrl}"`);
102
+ }
103
+ }
104
+ // Build validated skill if no critical errors
105
+ if (errors.length === 0 && name && author && description && id) {
106
+ const validatedSkill = {
107
+ id,
108
+ name,
109
+ description,
110
+ author,
111
+ repo_url: repoUrl,
112
+ quality_score: normalizedScore,
113
+ trust_tier: normalizedTrustTier,
114
+ tags,
115
+ source,
116
+ };
117
+ return {
118
+ valid: true,
119
+ skill: validatedSkill,
120
+ original: raw,
121
+ errors: [],
122
+ warnings,
123
+ fixes,
124
+ };
125
+ }
126
+ return {
127
+ valid: false,
128
+ skill: null,
129
+ original: raw,
130
+ errors,
131
+ warnings,
132
+ fixes,
133
+ };
134
+ }
135
+ //# sourceMappingURL=field-validators.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"field-validators.js","sourceRoot":"","sources":["../../../../src/scripts/validation/field-validators.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * SMI-863: Skill Validation and Deduplication Pipeline
3
+ *
4
+ * Validates skill data against schema rules and deduplicates
5
+ * entries using repository URL as primary key with source priority.
6
+ *
7
+ * Usage:
8
+ * npx tsx packages/core/src/scripts/validate-skills.ts [--input skills.json] [--output-dir data]
9
+ *
10
+ * Validation Rules:
11
+ * 1. Name present (non-empty)
12
+ * 2. Author present (use repo owner if missing)
13
+ * 3. Description present (use first 100 chars of name if missing)
14
+ * 4. Valid ID format (author/name)
15
+ * 5. Quality score 0-100
16
+ * 6. Valid trust tier enum
17
+ *
18
+ * Deduplication:
19
+ * - Primary key: repo_url
20
+ * - Source priority: anthropic-official (100) > github (80) > claude-plugins (40)
21
+ * - Keep higher quality score on conflict
22
+ * - Semantic similarity detection (threshold 0.85)
23
+ */
24
+ export * from './types.js';
25
+ export * from './normalizers.js';
26
+ export * from './field-validators.js';
27
+ export * from './deduplication.js';
28
+ export { runValidationPipeline } from './pipeline.js';
29
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/scripts/validation/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAOH,cAAc,YAAY,CAAA;AAC1B,cAAc,kBAAkB,CAAA;AAChC,cAAc,uBAAuB,CAAA;AACrC,cAAc,oBAAoB,CAAA;AAClC,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * SMI-863: Skill Validation and Deduplication Pipeline
3
+ *
4
+ * Validates skill data against schema rules and deduplicates
5
+ * entries using repository URL as primary key with source priority.
6
+ *
7
+ * Usage:
8
+ * npx tsx packages/core/src/scripts/validate-skills.ts [--input skills.json] [--output-dir data]
9
+ *
10
+ * Validation Rules:
11
+ * 1. Name present (non-empty)
12
+ * 2. Author present (use repo owner if missing)
13
+ * 3. Description present (use first 100 chars of name if missing)
14
+ * 4. Valid ID format (author/name)
15
+ * 5. Quality score 0-100
16
+ * 6. Valid trust tier enum
17
+ *
18
+ * Deduplication:
19
+ * - Primary key: repo_url
20
+ * - Source priority: anthropic-official (100) > github (80) > claude-plugins (40)
21
+ * - Keep higher quality score on conflict
22
+ * - Semantic similarity detection (threshold 0.85)
23
+ */
24
+ import * as fs from 'fs';
25
+ import { CONFIG } from './types.js';
26
+ import { runValidationPipeline } from './pipeline.js';
27
+ // Re-export all types and functions for external use
28
+ export * from './types.js';
29
+ export * from './normalizers.js';
30
+ export * from './field-validators.js';
31
+ export * from './deduplication.js';
32
+ export { runValidationPipeline } from './pipeline.js';
33
+ // ============================================================================
34
+ // CLI Entry Point
35
+ // ============================================================================
36
+ async function main() {
37
+ const args = process.argv.slice(2);
38
+ // Parse arguments
39
+ let inputPath = CONFIG.DEFAULT_INPUT;
40
+ let outputDir = CONFIG.DEFAULT_OUTPUT_DIR;
41
+ for (let i = 0; i < args.length; i++) {
42
+ if (args[i] === '--input' && args[i + 1]) {
43
+ inputPath = args[++i];
44
+ }
45
+ else if (args[i] === '--output-dir' && args[i + 1]) {
46
+ outputDir = args[++i];
47
+ }
48
+ else if (args[i] === '--help') {
49
+ console.log(`
50
+ Usage: npx tsx packages/core/src/scripts/validate-skills.ts [options]
51
+
52
+ Options:
53
+ --input <path> Path to input JSON file (default: ${CONFIG.DEFAULT_INPUT})
54
+ --output-dir <path> Output directory for results (default: ${CONFIG.DEFAULT_OUTPUT_DIR})
55
+ --help Show this help message
56
+
57
+ Output files:
58
+ validated-skills.json Clean, deduplicated skill data
59
+ validation-report.json Validation statistics and errors
60
+ duplicates-report.json Detected duplicate entries
61
+ `);
62
+ process.exit(0);
63
+ }
64
+ }
65
+ // Validate input file exists
66
+ if (!fs.existsSync(inputPath)) {
67
+ console.error(`Error: Input file not found: ${inputPath}`);
68
+ process.exit(1);
69
+ }
70
+ try {
71
+ await runValidationPipeline(inputPath, outputDir);
72
+ }
73
+ catch (error) {
74
+ console.error('Pipeline failed:', error);
75
+ process.exit(1);
76
+ }
77
+ }
78
+ // Run if executed directly
79
+ const isMainModule = process.argv[1]?.includes('validate-skills') ||
80
+ process.argv[1]?.includes('validation/index');
81
+ if (isMainModule) {
82
+ main().catch(console.error);
83
+ }
84
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/scripts/validation/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,MAAM,IAAI,CAAA;AACxB,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AACnC,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA;AAErD,qDAAqD;AACrD,cAAc,YAAY,CAAA;AAC1B,cAAc,kBAAkB,CAAA;AAChC,cAAc,uBAAuB,CAAA;AACrC,cAAc,oBAAoB,CAAA;AAClC,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA;AAErD,+EAA+E;AAC/E,kBAAkB;AAClB,+EAA+E;AAE/E,KAAK,UAAU,IAAI;IACjB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;IAElC,kBAAkB;IAClB,IAAI,SAAS,GAAW,MAAM,CAAC,aAAa,CAAA;IAC5C,IAAI,SAAS,GAAW,MAAM,CAAC,kBAAkB,CAAA;IAEjD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,SAAS,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YACzC,SAAS,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAA;QACvB,CAAC;aAAM,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,cAAc,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YACrD,SAAS,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAA;QACvB,CAAC;aAAM,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ,EAAE,CAAC;YAChC,OAAO,CAAC,GAAG,CAAC;;;;2DAIyC,MAAM,CAAC,aAAa;gEACf,MAAM,CAAC,kBAAkB;;;;;;;CAOxF,CAAC,CAAA;YACI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACjB,CAAC;IACH,CAAC;IAED,6BAA6B;IAC7B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC9B,OAAO,CAAC,KAAK,CAAC,gCAAgC,SAAS,EAAE,CAAC,CAAA;QAC1D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,qBAAqB,CAAC,SAAS,EAAE,SAAS,CAAC,CAAA;IACnD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,kBAAkB,EAAE,KAAK,CAAC,CAAA;QACxC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;AACH,CAAC;AAED,2BAA2B;AAC3B,MAAM,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,iBAAiB,CAAC;IAC5C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,kBAAkB,CAAC,CAAA;AAClE,IAAI,YAAY,EAAE,CAAC;IACjB,IAAI,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;AAC7B,CAAC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * SMI-863: Normalization utilities for skill validation
3
+ */
4
+ import { TrustTier } from './types.js';
5
+ /**
6
+ * Extract owner from repo URL
7
+ */
8
+ export declare function extractOwnerFromRepoUrl(repoUrl: string | null | undefined): string | null;
9
+ /**
10
+ * Generate skill ID from author and name
11
+ */
12
+ export declare function generateSkillId(author: string, name: string): string;
13
+ /**
14
+ * Normalize quality score to 0-100 range
15
+ */
16
+ export declare function normalizeQualityScore(score: number | null | undefined): number;
17
+ /**
18
+ * Normalize trust tier to valid enum value
19
+ */
20
+ export declare function normalizeTrustTier(tier: string | null | undefined): TrustTier;
21
+ /**
22
+ * Normalize source name
23
+ */
24
+ export declare function normalizeSource(source: string | null | undefined): string;
25
+ /**
26
+ * Generate hash for repo URL deduplication
27
+ */
28
+ export declare function hashRepoUrl(repoUrl: string): string;
29
+ //# sourceMappingURL=normalizers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalizers.d.ts","sourceRoot":"","sources":["../../../../src/scripts/validation/normalizers.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAEtC;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAUzF;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAQpE;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAU9E;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,SAAS,CAmB7E;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAGzE;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEnD"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * SMI-863: Normalization utilities for skill validation
3
+ */
4
+ import { createHash } from 'crypto';
5
+ /**
6
+ * Extract owner from repo URL
7
+ */
8
+ export function extractOwnerFromRepoUrl(repoUrl) {
9
+ if (!repoUrl)
10
+ return null;
11
+ try {
12
+ const url = new URL(repoUrl);
13
+ const parts = url.pathname.split('/').filter(Boolean);
14
+ return parts[0] || null;
15
+ }
16
+ catch {
17
+ return null;
18
+ }
19
+ }
20
+ /**
21
+ * Generate skill ID from author and name
22
+ */
23
+ export function generateSkillId(author, name) {
24
+ const sanitize = (s) => s
25
+ .toLowerCase()
26
+ .replace(/[^a-z0-9-_]/g, '-')
27
+ .replace(/-+/g, '-')
28
+ .replace(/^-|-$/g, '');
29
+ return `${sanitize(author)}/${sanitize(name)}`;
30
+ }
31
+ /**
32
+ * Normalize quality score to 0-100 range
33
+ */
34
+ export function normalizeQualityScore(score) {
35
+ if (score === null || score === undefined)
36
+ return 50; // Default score
37
+ // If score is 0-1, convert to 0-100
38
+ if (score >= 0 && score <= 1) {
39
+ return Math.round(score * 100);
40
+ }
41
+ // Clamp to 0-100
42
+ return Math.max(0, Math.min(100, Math.round(score)));
43
+ }
44
+ /**
45
+ * Normalize trust tier to valid enum value
46
+ */
47
+ export function normalizeTrustTier(tier) {
48
+ if (!tier)
49
+ return 'unknown';
50
+ const normalized = tier.toLowerCase().trim();
51
+ // Map common variations
52
+ const mappings = {
53
+ verified: 'verified',
54
+ official: 'verified',
55
+ 'anthropic-official': 'verified',
56
+ community: 'community',
57
+ experimental: 'experimental',
58
+ beta: 'experimental',
59
+ unknown: 'unknown',
60
+ unverified: 'unknown',
61
+ standard: 'community',
62
+ };
63
+ return mappings[normalized] || 'unknown';
64
+ }
65
+ /**
66
+ * Normalize source name
67
+ */
68
+ export function normalizeSource(source) {
69
+ if (!source)
70
+ return 'unknown';
71
+ return source.toLowerCase().trim();
72
+ }
73
+ /**
74
+ * Generate hash for repo URL deduplication
75
+ */
76
+ export function hashRepoUrl(repoUrl) {
77
+ return createHash('md5').update(repoUrl.toLowerCase().trim()).digest('hex');
78
+ }
79
+ //# sourceMappingURL=normalizers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalizers.js","sourceRoot":"","sources":["../../../../src/scripts/validation/normalizers.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AAGnC;;GAEG;AACH,MAAM,UAAU,uBAAuB,CAAC,OAAkC;IACxE,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAA;IAEzB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAA;QAC5B,MAAM,KAAK,GAAG,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;QACrD,OAAO,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,CAAA;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,MAAc,EAAE,IAAY;IAC1D,MAAM,QAAQ,GAAG,CAAC,CAAS,EAAE,EAAE,CAC7B,CAAC;SACE,WAAW,EAAE;SACb,OAAO,CAAC,cAAc,EAAE,GAAG,CAAC;SAC5B,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAA;IAC1B,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAA;AAChD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB,CAAC,KAAgC;IACpE,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,EAAE,CAAA,CAAC,gBAAgB;IAErE,oCAAoC;IACpC,IAAI,KAAK,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;QAC7B,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,GAAG,CAAC,CAAA;IAChC,CAAC;IAED,iBAAiB;IACjB,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;AACtD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAA+B;IAChE,IAAI,CAAC,IAAI;QAAE,OAAO,SAAS,CAAA;IAE3B,MAAM,UAAU,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAA;IAE5C,wBAAwB;IACxB,MAAM,QAAQ,GAA8B;QAC1C,QAAQ,EAAE,UAAU;QACpB,QAAQ,EAAE,UAAU;QACpB,oBAAoB,EAAE,UAAU;QAChC,SAAS,EAAE,WAAW;QACtB,YAAY,EAAE,cAAc;QAC5B,IAAI,EAAE,cAAc;QACpB,OAAO,EAAE,SAAS;QAClB,UAAU,EAAE,SAAS;QACrB,QAAQ,EAAE,WAAW;KACtB,CAAA;IAED,OAAO,QAAQ,CAAC,UAAU,CAAC,IAAI,SAAS,CAAA;AAC1C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,MAAiC;IAC/D,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAA;IAC7B,OAAO,MAAM,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAA;AACpC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,OAAe;IACzC,OAAO,UAAU,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AAC7E,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * SMI-863: Validation pipeline for skill processing
3
+ */
4
+ import { ValidatedSkill, ValidationReport, DuplicatesReport } from './types.js';
5
+ /**
6
+ * Run the complete validation and deduplication pipeline
7
+ */
8
+ export declare function runValidationPipeline(inputPath: string, outputDir: string): Promise<{
9
+ validatedSkills: ValidatedSkill[];
10
+ validationReport: ValidationReport;
11
+ duplicatesReport: DuplicatesReport;
12
+ }>;
13
+ //# sourceMappingURL=pipeline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../../../../src/scripts/validation/pipeline.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EAEL,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EACjB,MAAM,YAAY,CAAA;AAInB;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;IACT,eAAe,EAAE,cAAc,EAAE,CAAA;IACjC,gBAAgB,EAAE,gBAAgB,CAAA;IAClC,gBAAgB,EAAE,gBAAgB,CAAA;CACnC,CAAC,CAqID"}