@skillsmith/core 0.9.0 → 0.11.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 (404) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/src/analysis/tree-sitter/pythonIncremental.d.ts +23 -0
  4. package/dist/src/analysis/tree-sitter/pythonIncremental.d.ts.map +1 -1
  5. package/dist/src/analysis/tree-sitter/pythonIncremental.hardening.test.js +137 -0
  6. package/dist/src/analysis/tree-sitter/pythonIncremental.hardening.test.js.map +1 -1
  7. package/dist/src/analysis/tree-sitter/pythonIncremental.js +83 -10
  8. package/dist/src/analysis/tree-sitter/pythonIncremental.js.map +1 -1
  9. package/dist/src/analysis/tree-sitter/queryExtractionMatchesOrExceedsRegex.test.js +6 -1
  10. package/dist/src/analysis/tree-sitter/queryExtractionMatchesOrExceedsRegex.test.js.map +1 -1
  11. package/dist/src/api/client.d.ts.map +1 -1
  12. package/dist/src/api/client.js +6 -0
  13. package/dist/src/api/client.js.map +1 -1
  14. package/dist/src/api/client.test.d.ts +9 -0
  15. package/dist/src/api/client.test.d.ts.map +1 -0
  16. package/dist/src/api/client.test.js +81 -0
  17. package/dist/src/api/client.test.js.map +1 -0
  18. package/dist/src/config/audit-notify-state.d.ts +46 -0
  19. package/dist/src/config/audit-notify-state.d.ts.map +1 -0
  20. package/dist/src/config/audit-notify-state.js +55 -0
  21. package/dist/src/config/audit-notify-state.js.map +1 -0
  22. package/dist/src/config/audit-notify-state.test.d.ts +9 -0
  23. package/dist/src/config/audit-notify-state.test.d.ts.map +1 -0
  24. package/dist/src/config/audit-notify-state.test.js +63 -0
  25. package/dist/src/config/audit-notify-state.test.js.map +1 -0
  26. package/dist/src/config/index.d.ts +10 -0
  27. package/dist/src/config/index.d.ts.map +1 -1
  28. package/dist/src/config/index.js.map +1 -1
  29. package/dist/src/exports/services.d.ts +3 -1
  30. package/dist/src/exports/services.d.ts.map +1 -1
  31. package/dist/src/exports/services.js +9 -1
  32. package/dist/src/exports/services.js.map +1 -1
  33. package/dist/src/index.d.ts +6 -3
  34. package/dist/src/index.d.ts.map +1 -1
  35. package/dist/src/index.js +11 -2
  36. package/dist/src/index.js.map +1 -1
  37. package/dist/src/install/agent-config-merge.json-array.d.ts +29 -0
  38. package/dist/src/install/agent-config-merge.json-array.d.ts.map +1 -0
  39. package/dist/src/install/agent-config-merge.json-array.js +100 -0
  40. package/dist/src/install/agent-config-merge.json-array.js.map +1 -0
  41. package/dist/src/install/agent-config-merge.json.d.ts +37 -0
  42. package/dist/src/install/agent-config-merge.json.d.ts.map +1 -0
  43. package/dist/src/install/agent-config-merge.json.js +134 -0
  44. package/dist/src/install/agent-config-merge.json.js.map +1 -0
  45. package/dist/src/install/agent-config-merge.toml-block.d.ts +48 -0
  46. package/dist/src/install/agent-config-merge.toml-block.d.ts.map +1 -0
  47. package/dist/src/install/agent-config-merge.toml-block.js +107 -0
  48. package/dist/src/install/agent-config-merge.toml-block.js.map +1 -0
  49. package/dist/src/install/agent-config-merge.types.d.ts +87 -0
  50. package/dist/src/install/agent-config-merge.types.d.ts.map +1 -0
  51. package/dist/src/install/agent-config-merge.types.js +83 -0
  52. package/dist/src/install/agent-config-merge.types.js.map +1 -0
  53. package/dist/src/install/agent-config-merge.yaml.d.ts +46 -0
  54. package/dist/src/install/agent-config-merge.yaml.d.ts.map +1 -0
  55. package/dist/src/install/agent-config-merge.yaml.js +133 -0
  56. package/dist/src/install/agent-config-merge.yaml.js.map +1 -0
  57. package/dist/src/install/agent-config-merge.yaml.test.d.ts +2 -0
  58. package/dist/src/install/agent-config-merge.yaml.test.d.ts.map +1 -0
  59. package/dist/src/install/agent-config-merge.yaml.test.js +210 -0
  60. package/dist/src/install/agent-config-merge.yaml.test.js.map +1 -0
  61. package/dist/src/install/agent-harness-targets.d.ts +98 -0
  62. package/dist/src/install/agent-harness-targets.d.ts.map +1 -0
  63. package/dist/src/install/agent-harness-targets.js +154 -0
  64. package/dist/src/install/agent-harness-targets.js.map +1 -0
  65. package/dist/src/install/agent-home-relocate.d.ts +29 -0
  66. package/dist/src/install/agent-home-relocate.d.ts.map +1 -0
  67. package/dist/src/install/agent-home-relocate.js +38 -0
  68. package/dist/src/install/agent-home-relocate.js.map +1 -0
  69. package/dist/src/install/agent-manifest-path-guard.d.ts +55 -0
  70. package/dist/src/install/agent-manifest-path-guard.d.ts.map +1 -0
  71. package/dist/src/install/agent-manifest-path-guard.js +109 -0
  72. package/dist/src/install/agent-manifest-path-guard.js.map +1 -0
  73. package/dist/src/install/agent-manifest-path-guard.test.d.ts +2 -0
  74. package/dist/src/install/agent-manifest-path-guard.test.d.ts.map +1 -0
  75. package/dist/src/install/agent-manifest-path-guard.test.js +72 -0
  76. package/dist/src/install/agent-manifest-path-guard.test.js.map +1 -0
  77. package/dist/src/install/agent-manifest.d.ts +58 -0
  78. package/dist/src/install/agent-manifest.d.ts.map +1 -0
  79. package/dist/src/install/agent-manifest.js +103 -0
  80. package/dist/src/install/agent-manifest.js.map +1 -0
  81. package/dist/src/install/agent-pack-installer.d.ts +39 -0
  82. package/dist/src/install/agent-pack-installer.d.ts.map +1 -0
  83. package/dist/src/install/agent-pack-installer.entry.d.ts +55 -0
  84. package/dist/src/install/agent-pack-installer.entry.d.ts.map +1 -0
  85. package/dist/src/install/agent-pack-installer.entry.js +90 -0
  86. package/dist/src/install/agent-pack-installer.entry.js.map +1 -0
  87. package/dist/src/install/agent-pack-installer.fs-helpers.d.ts +33 -0
  88. package/dist/src/install/agent-pack-installer.fs-helpers.d.ts.map +1 -0
  89. package/dist/src/install/agent-pack-installer.fs-helpers.js +59 -0
  90. package/dist/src/install/agent-pack-installer.fs-helpers.js.map +1 -0
  91. package/dist/src/install/agent-pack-installer.harness.d.ts +66 -0
  92. package/dist/src/install/agent-pack-installer.harness.d.ts.map +1 -0
  93. package/dist/src/install/agent-pack-installer.harness.js +310 -0
  94. package/dist/src/install/agent-pack-installer.harness.js.map +1 -0
  95. package/dist/src/install/agent-pack-installer.js +221 -0
  96. package/dist/src/install/agent-pack-installer.js.map +1 -0
  97. package/dist/src/install/agent-pack-installer.preserve.test.d.ts +11 -0
  98. package/dist/src/install/agent-pack-installer.preserve.test.d.ts.map +1 -0
  99. package/dist/src/install/agent-pack-installer.preserve.test.js +72 -0
  100. package/dist/src/install/agent-pack-installer.preserve.test.js.map +1 -0
  101. package/dist/src/install/agent-pack-installer.test.d.ts +2 -0
  102. package/dist/src/install/agent-pack-installer.test.d.ts.map +1 -0
  103. package/dist/src/install/agent-pack-installer.test.js +350 -0
  104. package/dist/src/install/agent-pack-installer.test.js.map +1 -0
  105. package/dist/src/install/agent-pack-installer.types.d.ts +51 -0
  106. package/dist/src/install/agent-pack-installer.types.d.ts.map +1 -0
  107. package/dist/src/install/agent-pack-installer.types.js +16 -0
  108. package/dist/src/install/agent-pack-installer.types.js.map +1 -0
  109. package/dist/src/install/agent-pack-uninstaller.d.ts +43 -0
  110. package/dist/src/install/agent-pack-uninstaller.d.ts.map +1 -0
  111. package/dist/src/install/agent-pack-uninstaller.js +113 -0
  112. package/dist/src/install/agent-pack-uninstaller.js.map +1 -0
  113. package/dist/src/install/agent-pack-uninstaller.test.d.ts +2 -0
  114. package/dist/src/install/agent-pack-uninstaller.test.d.ts.map +1 -0
  115. package/dist/src/install/agent-pack-uninstaller.test.js +212 -0
  116. package/dist/src/install/agent-pack-uninstaller.test.js.map +1 -0
  117. package/dist/src/install/index.d.ts +7 -0
  118. package/dist/src/install/index.d.ts.map +1 -1
  119. package/dist/src/install/index.js +7 -0
  120. package/dist/src/install/index.js.map +1 -1
  121. package/dist/src/install/paths.d.ts +1 -1
  122. package/dist/src/install/paths.d.ts.map +1 -1
  123. package/dist/src/install/paths.js +4 -0
  124. package/dist/src/install/paths.js.map +1 -1
  125. package/dist/src/install/paths.test.js +15 -0
  126. package/dist/src/install/paths.test.js.map +1 -1
  127. package/dist/src/journal/hash.d.ts +13 -0
  128. package/dist/src/journal/hash.d.ts.map +1 -0
  129. package/dist/src/journal/hash.js +16 -0
  130. package/dist/src/journal/hash.js.map +1 -0
  131. package/dist/src/journal/index.d.ts +15 -0
  132. package/dist/src/journal/index.d.ts.map +1 -0
  133. package/dist/src/journal/index.js +15 -0
  134. package/dist/src/journal/index.js.map +1 -0
  135. package/dist/src/journal/journal.test.d.ts +16 -0
  136. package/dist/src/journal/journal.test.d.ts.map +1 -0
  137. package/dist/src/journal/journal.test.js +171 -0
  138. package/dist/src/journal/journal.test.js.map +1 -0
  139. package/dist/src/journal/path.d.ts +44 -0
  140. package/dist/src/journal/path.d.ts.map +1 -0
  141. package/dist/src/journal/path.js +61 -0
  142. package/dist/src/journal/path.js.map +1 -0
  143. package/dist/src/journal/reader.d.ts +38 -0
  144. package/dist/src/journal/reader.d.ts.map +1 -0
  145. package/dist/src/journal/reader.js +93 -0
  146. package/dist/src/journal/reader.js.map +1 -0
  147. package/dist/src/journal/types.d.ts +87 -0
  148. package/dist/src/journal/types.d.ts.map +1 -0
  149. package/dist/src/journal/types.js +21 -0
  150. package/dist/src/journal/types.js.map +1 -0
  151. package/dist/src/journal/writer.d.ts +52 -0
  152. package/dist/src/journal/writer.d.ts.map +1 -0
  153. package/dist/src/journal/writer.js +125 -0
  154. package/dist/src/journal/writer.js.map +1 -0
  155. package/dist/src/logging/context.d.ts +58 -0
  156. package/dist/src/logging/context.d.ts.map +1 -0
  157. package/dist/src/logging/context.js +62 -0
  158. package/dist/src/logging/context.js.map +1 -0
  159. package/dist/src/logging/context.test.d.ts +14 -0
  160. package/dist/src/logging/context.test.d.ts.map +1 -0
  161. package/dist/src/logging/context.test.js +88 -0
  162. package/dist/src/logging/context.test.js.map +1 -0
  163. package/dist/src/logging/index.d.ts +13 -0
  164. package/dist/src/logging/index.d.ts.map +1 -0
  165. package/dist/src/logging/index.js +12 -0
  166. package/dist/src/logging/index.js.map +1 -0
  167. package/dist/src/logging/logger.d.ts +71 -0
  168. package/dist/src/logging/logger.d.ts.map +1 -0
  169. package/dist/src/logging/logger.js +264 -0
  170. package/dist/src/logging/logger.js.map +1 -0
  171. package/dist/src/logging/logger.test.d.ts +9 -0
  172. package/dist/src/logging/logger.test.d.ts.map +1 -0
  173. package/dist/src/logging/logger.test.js +320 -0
  174. package/dist/src/logging/logger.test.js.map +1 -0
  175. package/dist/src/logging/redact.d.ts +35 -0
  176. package/dist/src/logging/redact.d.ts.map +1 -0
  177. package/dist/src/logging/redact.js +152 -0
  178. package/dist/src/logging/redact.js.map +1 -0
  179. package/dist/src/logging/redact.test.d.ts +8 -0
  180. package/dist/src/logging/redact.test.d.ts.map +1 -0
  181. package/dist/src/logging/redact.test.js +330 -0
  182. package/dist/src/logging/redact.test.js.map +1 -0
  183. package/dist/src/logging/rotation.d.ts +75 -0
  184. package/dist/src/logging/rotation.d.ts.map +1 -0
  185. package/dist/src/logging/rotation.js +284 -0
  186. package/dist/src/logging/rotation.js.map +1 -0
  187. package/dist/src/logging/rotation.test.d.ts +11 -0
  188. package/dist/src/logging/rotation.test.d.ts.map +1 -0
  189. package/dist/src/logging/rotation.test.js +132 -0
  190. package/dist/src/logging/rotation.test.js.map +1 -0
  191. package/dist/src/logging/types.d.ts +69 -0
  192. package/dist/src/logging/types.d.ts.map +1 -0
  193. package/dist/src/logging/types.js +9 -0
  194. package/dist/src/logging/types.js.map +1 -0
  195. package/dist/src/paywall-triggers/index.d.ts +13 -0
  196. package/dist/src/paywall-triggers/index.d.ts.map +1 -0
  197. package/dist/src/paywall-triggers/index.js +13 -0
  198. package/dist/src/paywall-triggers/index.js.map +1 -0
  199. package/dist/src/paywall-triggers/path.d.ts +47 -0
  200. package/dist/src/paywall-triggers/path.d.ts.map +1 -0
  201. package/dist/src/paywall-triggers/path.js +73 -0
  202. package/dist/src/paywall-triggers/path.js.map +1 -0
  203. package/dist/src/paywall-triggers/store.d.ts +75 -0
  204. package/dist/src/paywall-triggers/store.d.ts.map +1 -0
  205. package/dist/src/paywall-triggers/store.js +122 -0
  206. package/dist/src/paywall-triggers/store.js.map +1 -0
  207. package/dist/src/paywall-triggers/store.test.d.ts +2 -0
  208. package/dist/src/paywall-triggers/store.test.d.ts.map +1 -0
  209. package/dist/src/paywall-triggers/store.test.js +121 -0
  210. package/dist/src/paywall-triggers/store.test.js.map +1 -0
  211. package/dist/src/paywall-triggers/types.d.ts +24 -0
  212. package/dist/src/paywall-triggers/types.d.ts.map +1 -0
  213. package/dist/src/paywall-triggers/types.js +13 -0
  214. package/dist/src/paywall-triggers/types.js.map +1 -0
  215. package/dist/src/security/index.d.ts +2 -0
  216. package/dist/src/security/index.d.ts.map +1 -1
  217. package/dist/src/security/index.js +4 -0
  218. package/dist/src/security/index.js.map +1 -1
  219. package/dist/src/security/scanner/SecurityScanner.compound.d.ts +13 -0
  220. package/dist/src/security/scanner/SecurityScanner.compound.d.ts.map +1 -0
  221. package/dist/src/security/scanner/SecurityScanner.compound.js +127 -0
  222. package/dist/src/security/scanner/SecurityScanner.compound.js.map +1 -0
  223. package/dist/src/security/scanner/SecurityScanner.d.ts.map +1 -1
  224. package/dist/src/security/scanner/SecurityScanner.hostile-update.d.ts +46 -0
  225. package/dist/src/security/scanner/SecurityScanner.hostile-update.d.ts.map +1 -0
  226. package/dist/src/security/scanner/SecurityScanner.hostile-update.js +209 -0
  227. package/dist/src/security/scanner/SecurityScanner.hostile-update.js.map +1 -0
  228. package/dist/src/security/scanner/SecurityScanner.js +10 -1
  229. package/dist/src/security/scanner/SecurityScanner.js.map +1 -1
  230. package/dist/src/security/scanner/SecurityScanner.pii.d.ts +23 -0
  231. package/dist/src/security/scanner/SecurityScanner.pii.d.ts.map +1 -0
  232. package/dist/src/security/scanner/SecurityScanner.pii.js +152 -0
  233. package/dist/src/security/scanner/SecurityScanner.pii.js.map +1 -0
  234. package/dist/src/security/scanner/SecurityScanner.scanners.d.ts +5 -12
  235. package/dist/src/security/scanner/SecurityScanner.scanners.d.ts.map +1 -1
  236. package/dist/src/security/scanner/SecurityScanner.scanners.js +63 -137
  237. package/dist/src/security/scanner/SecurityScanner.scanners.js.map +1 -1
  238. package/dist/src/security/scanner/index.d.ts +2 -1
  239. package/dist/src/security/scanner/index.d.ts.map +1 -1
  240. package/dist/src/security/scanner/index.js +2 -0
  241. package/dist/src/security/scanner/index.js.map +1 -1
  242. package/dist/src/security/scanner/patterns.d.ts +2 -0
  243. package/dist/src/security/scanner/patterns.d.ts.map +1 -1
  244. package/dist/src/security/scanner/patterns.js +79 -11
  245. package/dist/src/security/scanner/patterns.js.map +1 -1
  246. package/dist/src/security/scanner/types.d.ts +23 -0
  247. package/dist/src/security/scanner/types.d.ts.map +1 -1
  248. package/dist/src/services/agent-pack/agent-pack.test.d.ts +18 -0
  249. package/dist/src/services/agent-pack/agent-pack.test.d.ts.map +1 -0
  250. package/dist/src/services/agent-pack/agent-pack.test.js +344 -0
  251. package/dist/src/services/agent-pack/agent-pack.test.js.map +1 -0
  252. package/dist/src/services/agent-pack/hooks.d.ts +29 -0
  253. package/dist/src/services/agent-pack/hooks.d.ts.map +1 -0
  254. package/dist/src/services/agent-pack/hooks.js +139 -0
  255. package/dist/src/services/agent-pack/hooks.js.map +1 -0
  256. package/dist/src/services/agent-pack/index.d.ts +26 -0
  257. package/dist/src/services/agent-pack/index.d.ts.map +1 -0
  258. package/dist/src/services/agent-pack/index.js +109 -0
  259. package/dist/src/services/agent-pack/index.js.map +1 -0
  260. package/dist/src/services/agent-pack/prompt-source.d.ts +47 -0
  261. package/dist/src/services/agent-pack/prompt-source.d.ts.map +1 -0
  262. package/dist/src/services/agent-pack/prompt-source.js +182 -0
  263. package/dist/src/services/agent-pack/prompt-source.js.map +1 -0
  264. package/dist/src/services/agent-pack/shims.d.ts +40 -0
  265. package/dist/src/services/agent-pack/shims.d.ts.map +1 -0
  266. package/dist/src/services/agent-pack/shims.js +96 -0
  267. package/dist/src/services/agent-pack/shims.js.map +1 -0
  268. package/dist/src/services/agent-pack/skill-md.d.ts +35 -0
  269. package/dist/src/services/agent-pack/skill-md.d.ts.map +1 -0
  270. package/dist/src/services/agent-pack/skill-md.js +89 -0
  271. package/dist/src/services/agent-pack/skill-md.js.map +1 -0
  272. package/dist/src/services/agent-pack/types.d.ts +118 -0
  273. package/dist/src/services/agent-pack/types.d.ts.map +1 -0
  274. package/dist/src/services/agent-pack/types.js +61 -0
  275. package/dist/src/services/agent-pack/types.js.map +1 -0
  276. package/dist/src/services/agent-tool-profile.d.ts +59 -0
  277. package/dist/src/services/agent-tool-profile.d.ts.map +1 -0
  278. package/dist/src/services/agent-tool-profile.js +76 -0
  279. package/dist/src/services/agent-tool-profile.js.map +1 -0
  280. package/dist/src/services/agent-tool-profile.test.d.ts +2 -0
  281. package/dist/src/services/agent-tool-profile.test.d.ts.map +1 -0
  282. package/dist/src/services/agent-tool-profile.test.js +28 -0
  283. package/dist/src/services/agent-tool-profile.test.js.map +1 -0
  284. package/dist/src/services/bundled-sibling-scan.d.ts +111 -0
  285. package/dist/src/services/bundled-sibling-scan.d.ts.map +1 -0
  286. package/dist/src/services/bundled-sibling-scan.js +170 -0
  287. package/dist/src/services/bundled-sibling-scan.js.map +1 -0
  288. package/dist/src/services/skill-installation.io.d.ts +16 -5
  289. package/dist/src/services/skill-installation.io.d.ts.map +1 -1
  290. package/dist/src/services/skill-installation.io.js +63 -22
  291. package/dist/src/services/skill-installation.io.js.map +1 -1
  292. package/dist/src/services/skill-installation.policy.d.ts +96 -0
  293. package/dist/src/services/skill-installation.policy.d.ts.map +1 -0
  294. package/dist/src/services/skill-installation.policy.js +144 -0
  295. package/dist/src/services/skill-installation.policy.js.map +1 -0
  296. package/dist/src/services/skill-installation.service.d.ts.map +1 -1
  297. package/dist/src/services/skill-installation.service.js +9 -3
  298. package/dist/src/services/skill-installation.service.js.map +1 -1
  299. package/dist/src/sources/index.d.ts +1 -0
  300. package/dist/src/sources/index.d.ts.map +1 -1
  301. package/dist/src/sources/index.js +4 -0
  302. package/dist/src/sources/index.js.map +1 -1
  303. package/dist/src/sync/access-token.d.ts +27 -0
  304. package/dist/src/sync/access-token.d.ts.map +1 -0
  305. package/dist/src/sync/access-token.js +40 -0
  306. package/dist/src/sync/access-token.js.map +1 -0
  307. package/dist/src/sync/audit-notify-client.d.ts +83 -0
  308. package/dist/src/sync/audit-notify-client.d.ts.map +1 -0
  309. package/dist/src/sync/audit-notify-client.js +126 -0
  310. package/dist/src/sync/audit-notify-client.js.map +1 -0
  311. package/dist/src/sync/audit-notify-client.test.d.ts +14 -0
  312. package/dist/src/sync/audit-notify-client.test.d.ts.map +1 -0
  313. package/dist/src/sync/audit-notify-client.test.js +133 -0
  314. package/dist/src/sync/audit-notify-client.test.js.map +1 -0
  315. package/dist/src/sync/index.d.ts +2 -1
  316. package/dist/src/sync/index.d.ts.map +1 -1
  317. package/dist/src/sync/index.js +3 -1
  318. package/dist/src/sync/index.js.map +1 -1
  319. package/dist/src/sync/inventory-client.d.ts +16 -0
  320. package/dist/src/sync/inventory-client.d.ts.map +1 -1
  321. package/dist/src/sync/inventory-client.js +59 -16
  322. package/dist/src/sync/inventory-client.js.map +1 -1
  323. package/dist/src/sync/inventory-client.test.js +67 -1
  324. package/dist/src/sync/inventory-client.test.js.map +1 -1
  325. package/dist/src/sync/inventory-collector.d.ts.map +1 -1
  326. package/dist/src/sync/inventory-collector.js +32 -5
  327. package/dist/src/sync/inventory-collector.js.map +1 -1
  328. package/dist/src/sync/inventory-collector.test.js +50 -1
  329. package/dist/src/sync/inventory-collector.test.js.map +1 -1
  330. package/dist/src/sync/inventory-types.d.ts +9 -0
  331. package/dist/src/sync/inventory-types.d.ts.map +1 -1
  332. package/dist/src/sync/inventory-types.js +3 -0
  333. package/dist/src/sync/inventory-types.js.map +1 -1
  334. package/dist/src/telemetry/agent-marker.d.ts +137 -0
  335. package/dist/src/telemetry/agent-marker.d.ts.map +1 -0
  336. package/dist/src/telemetry/agent-marker.js +242 -0
  337. package/dist/src/telemetry/agent-marker.js.map +1 -0
  338. package/dist/src/telemetry/agent-marker.test.d.ts +13 -0
  339. package/dist/src/telemetry/agent-marker.test.d.ts.map +1 -0
  340. package/dist/src/telemetry/agent-marker.test.js +202 -0
  341. package/dist/src/telemetry/agent-marker.test.js.map +1 -0
  342. package/dist/src/telemetry/index.d.ts +2 -1
  343. package/dist/src/telemetry/index.d.ts.map +1 -1
  344. package/dist/src/telemetry/index.js +6 -1
  345. package/dist/src/telemetry/index.js.map +1 -1
  346. package/dist/src/telemetry/posthog.d.ts +25 -0
  347. package/dist/src/telemetry/posthog.d.ts.map +1 -1
  348. package/dist/src/telemetry/posthog.js +10 -1
  349. package/dist/src/telemetry/posthog.js.map +1 -1
  350. package/dist/src/telemetry/wrap.bench.js +5 -0
  351. package/dist/src/telemetry/wrap.bench.js.map +1 -1
  352. package/dist/src/telemetry/wrap.correlation.test.d.ts +20 -0
  353. package/dist/src/telemetry/wrap.correlation.test.d.ts.map +1 -0
  354. package/dist/src/telemetry/wrap.correlation.test.js +174 -0
  355. package/dist/src/telemetry/wrap.correlation.test.js.map +1 -0
  356. package/dist/src/telemetry/wrap.d.ts +28 -7
  357. package/dist/src/telemetry/wrap.d.ts.map +1 -1
  358. package/dist/src/telemetry/wrap.gate.test.d.ts +22 -0
  359. package/dist/src/telemetry/wrap.gate.test.d.ts.map +1 -0
  360. package/dist/src/telemetry/wrap.gate.test.js +202 -0
  361. package/dist/src/telemetry/wrap.gate.test.js.map +1 -0
  362. package/dist/src/telemetry/wrap.js +196 -52
  363. package/dist/src/telemetry/wrap.js.map +1 -1
  364. package/dist/src/telemetry/wrap.marker.test.d.ts +16 -0
  365. package/dist/src/telemetry/wrap.marker.test.d.ts.map +1 -0
  366. package/dist/src/telemetry/wrap.marker.test.js +190 -0
  367. package/dist/src/telemetry/wrap.marker.test.js.map +1 -0
  368. package/dist/src/telemetry/wrap.test.js +14 -0
  369. package/dist/src/telemetry/wrap.test.js.map +1 -1
  370. package/dist/src/types.d.ts +6 -0
  371. package/dist/src/types.d.ts.map +1 -1
  372. package/dist/tests/SecurityScanner.exec.test.js +60 -0
  373. package/dist/tests/SecurityScanner.exec.test.js.map +1 -1
  374. package/dist/tests/security/ContinuousSecurity.test.js +10 -4
  375. package/dist/tests/security/ContinuousSecurity.test.js.map +1 -1
  376. package/dist/tests/security/SecurityScanner.chmod-evasion.test.d.ts +2 -0
  377. package/dist/tests/security/SecurityScanner.chmod-evasion.test.d.ts.map +1 -0
  378. package/dist/tests/security/SecurityScanner.chmod-evasion.test.js +126 -0
  379. package/dist/tests/security/SecurityScanner.chmod-evasion.test.js.map +1 -0
  380. package/dist/tests/security/chmod-compound.test.d.ts +2 -0
  381. package/dist/tests/security/chmod-compound.test.d.ts.map +1 -0
  382. package/dist/tests/security/chmod-compound.test.js +188 -0
  383. package/dist/tests/security/chmod-compound.test.js.map +1 -0
  384. package/dist/tests/security/pii-detection.test.js +24 -0
  385. package/dist/tests/security/pii-detection.test.js.map +1 -1
  386. package/dist/tests/security/scanner-regression-guard.test.d.ts +23 -7
  387. package/dist/tests/security/scanner-regression-guard.test.d.ts.map +1 -1
  388. package/dist/tests/security/scanner-regression-guard.test.js +206 -12
  389. package/dist/tests/security/scanner-regression-guard.test.js.map +1 -1
  390. package/dist/tests/security/sensitive-path-fp.test.d.ts +2 -0
  391. package/dist/tests/security/sensitive-path-fp.test.d.ts.map +1 -0
  392. package/dist/tests/security/sensitive-path-fp.test.js +142 -0
  393. package/dist/tests/security/sensitive-path-fp.test.js.map +1 -0
  394. package/dist/tests/services/bundled-sibling-scan.test.d.ts +2 -0
  395. package/dist/tests/services/bundled-sibling-scan.test.d.ts.map +1 -0
  396. package/dist/tests/services/bundled-sibling-scan.test.js +139 -0
  397. package/dist/tests/services/bundled-sibling-scan.test.js.map +1 -0
  398. package/dist/tests/unit/services/skill-installation.io.test.js +166 -0
  399. package/dist/tests/unit/services/skill-installation.io.test.js.map +1 -1
  400. package/dist/tests/unit/services/skill-installation.policy.test.d.ts +8 -0
  401. package/dist/tests/unit/services/skill-installation.policy.test.d.ts.map +1 -0
  402. package/dist/tests/unit/services/skill-installation.policy.test.js +151 -0
  403. package/dist/tests/unit/services/skill-installation.policy.test.js.map +1 -0
  404. package/package.json +28 -3
@@ -0,0 +1,284 @@
1
+ /**
2
+ * SMI-5615: Per-surface serialized JSONL writer with daily/size rollover and
3
+ * retention sweep.
4
+ *
5
+ * Write-serialization invariant (F2, from
6
+ * docs/internal/implementation/production-error-logging.md — the plan's
7
+ * original P-5 draft omitted this; it was the Opus `concurrency-auditor`
8
+ * plan-audit's most likely real-world race):
9
+ *
10
+ * A redacted error record (stack ≤20 frames) can exceed `PIPE_BUF`
11
+ * (4096 bytes), so concurrent, independent `appendFile`/`appendFileSync`
12
+ * calls from parallel async tool invocations are NOT safe here — two
13
+ * large concurrent writes can interleave/tear into one invalid JSONL line.
14
+ *
15
+ * Fix: one long-lived `fs.createWriteStream(path, { flags: 'a' })` per
16
+ * surface, created lazily on first write and cached in a module-scoped
17
+ * map. ALL writes for a given surface go through THIS single stream.
18
+ *
19
+ * That alone (Node serializing writes queued on one stream) would already
20
+ * prevent tearing between two writes to the SAME stream object. This
21
+ * module goes one step further for simplicity and an even stronger
22
+ * guarantee: every write is wrapped in an async mutex (`runExclusive`) keyed
23
+ * by surface, so at most one write is ever in flight to a surface's
24
+ * underlying file descriptor at a time — including the write that decides
25
+ * whether a daily/size rollover is needed. That decision-and-possible-swap
26
+ * (open a new stream, `end()` the old one) happens INSIDE the same
27
+ * exclusive section as the write that triggered it, so a rotation can
28
+ * never race a write: no write can land on a stream that has already been
29
+ * told to `end()`, and no two writers can simultaneously decide "today's
30
+ * file doesn't exist yet" and both create a stream.
31
+ *
32
+ * Daily rollover: `skillsmith-<surface>-<YYYY-MM-DD>.jsonl`, keyed off the
33
+ * calendar date at write time (mocked by `vi.setSystemTime` in tests — no
34
+ * separate clock seam needed).
35
+ *
36
+ * Size cap: ~10MB per file. When the currently-open file for TODAY would
37
+ * exceed the cap, roll to a `.1`/`.2`/... suffixed continuation file for the
38
+ * same day (`skillsmith-<surface>-<YYYY-MM-DD>.jsonl.<n>`), through the same
39
+ * serialization point as everything else.
40
+ *
41
+ * Retention: on module init, asynchronously (NOT awaited — never blocks
42
+ * import) sweep `~/.skillsmith/logs/` and delete files whose mtime is older
43
+ * than 14 days. `pruneExpiredLogs` is also exported directly so tests can
44
+ * await a deterministic run against a temp directory instead of racing the
45
+ * fire-and-forget module-init sweep.
46
+ */
47
+ import { createWriteStream, existsSync, statSync } from 'node:fs';
48
+ import { mkdir, readdir, stat, unlink } from 'node:fs/promises';
49
+ import { homedir } from 'node:os';
50
+ import { join } from 'node:path';
51
+ const SIZE_CAP_BYTES = 10 * 1024 * 1024; // ~10MB per file (F2)
52
+ const RETENTION_DAYS = 14;
53
+ /**
54
+ * Log directory. Overridable via `SKILLSMITH_LOG_DIR` — a test-only seam
55
+ * (not part of the plan's documented env-var surface) so `rotation.test.ts`
56
+ * can point writes/sweeps at a temp directory instead of the real
57
+ * `~/.skillsmith/logs/`. Read lazily (not frozen at import time) so a test
58
+ * can set the env var before its first write without needing
59
+ * `vi.resetModules()`.
60
+ */
61
+ function getLogDir() {
62
+ return process.env.SKILLSMITH_LOG_DIR || join(homedir(), '.skillsmith', 'logs');
63
+ }
64
+ function dailyFilePath(surface, date) {
65
+ return join(getLogDir(), `skillsmith-${surface}-${date}.jsonl`);
66
+ }
67
+ /** Next available `.N` continuation suffix for today's file, same day only. */
68
+ function nextRolledFilePath(surface, date) {
69
+ const base = dailyFilePath(surface, date);
70
+ let n = 1;
71
+ while (existsSync(`${base}.${n}`))
72
+ n++;
73
+ return `${base}.${n}`;
74
+ }
75
+ function statSizeOrZero(filePath) {
76
+ try {
77
+ return statSync(filePath).size;
78
+ }
79
+ catch {
80
+ return 0;
81
+ }
82
+ }
83
+ function todayDateString() {
84
+ return new Date().toISOString().split('T')[0];
85
+ }
86
+ // ---------------------------------------------------------------------------
87
+ // Async mutex — one FIFO queue per surface. `runExclusive` serializes both
88
+ // the rollover decision AND the write itself, so at most one write is ever
89
+ // in flight per surface (F2).
90
+ // ---------------------------------------------------------------------------
91
+ const queueTails = new Map();
92
+ function runExclusive(surface, task) {
93
+ const tail = queueTails.get(surface) ?? Promise.resolve();
94
+ // Run `task` after the prior tail settles, whether it resolved or
95
+ // rejected — one surface's failed write must not permanently jam the
96
+ // queue for that surface's subsequent writes.
97
+ const result = tail.then(task, task);
98
+ // Keep the queue's tail alive regardless of `task`'s outcome; the real
99
+ // outcome is still observable to the caller via `result`.
100
+ queueTails.set(surface, result.then(() => undefined, () => undefined));
101
+ return result;
102
+ }
103
+ const states = new Map();
104
+ function getState(surface) {
105
+ let state = states.get(surface);
106
+ if (!state) {
107
+ state = { stream: null, date: null, sizeBytes: 0 };
108
+ states.set(surface, state);
109
+ }
110
+ return state;
111
+ }
112
+ /**
113
+ * Ends a stream and resolves once it has fully finished (or errored) — never
114
+ * rejects, so a close failure can't block the caller from opening the
115
+ * replacement stream.
116
+ */
117
+ function closeStream(stream) {
118
+ return new Promise((resolve) => {
119
+ const done = () => resolve();
120
+ stream.once('error', done);
121
+ stream.end(done);
122
+ });
123
+ }
124
+ /**
125
+ * Opens `filePath` for append and resolves once the underlying fd is open
126
+ * (or rejects if `open()` itself fails, e.g. permission denied) — waiting
127
+ * for `'open'`/`'error'` rather than trusting `createWriteStream`'s
128
+ * synchronous return lets an unwritable path surface as a rejected Promise
129
+ * instead of a later unhandled `'error'` event.
130
+ */
131
+ function openStream(filePath) {
132
+ return new Promise((resolve, reject) => {
133
+ const stream = createWriteStream(filePath, { flags: 'a' });
134
+ const onOpen = () => {
135
+ cleanup();
136
+ resolve(stream);
137
+ };
138
+ const onError = (err) => {
139
+ cleanup();
140
+ reject(err);
141
+ };
142
+ function cleanup() {
143
+ stream.off('open', onOpen);
144
+ stream.off('error', onError);
145
+ }
146
+ stream.once('open', onOpen);
147
+ stream.once('error', onError);
148
+ }).then((stream) => {
149
+ // Persistent handler for errors that occur AFTER open (disk full, etc.)
150
+ // — required so an unlistened 'error' event never crashes the process.
151
+ // Actual write failures are still propagated to the caller via the
152
+ // write() callback in `writeChunk`; this is a pure safety net.
153
+ stream.on('error', (err) => {
154
+ console.error('[skillsmith] log stream error:', err instanceof Error ? err.message : err);
155
+ });
156
+ return stream;
157
+ });
158
+ }
159
+ function writeChunk(stream, buf) {
160
+ return new Promise((resolve, reject) => {
161
+ stream.write(buf, (err) => {
162
+ if (err)
163
+ reject(err);
164
+ else
165
+ resolve();
166
+ });
167
+ });
168
+ }
169
+ /**
170
+ * Resolves the stream to write to for `surface` RIGHT NOW, opening a new one
171
+ * (and ending the old one) if the calendar day changed or the current file
172
+ * has exceeded the size cap. Must only be called from inside
173
+ * `runExclusive(surface, ...)` — it is not itself lock-protected.
174
+ */
175
+ async function resolveStream(surface) {
176
+ const state = getState(surface);
177
+ const today = todayDateString();
178
+ const isNewDay = state.stream === null || state.date !== today;
179
+ const isOversized = !isNewDay && state.sizeBytes >= SIZE_CAP_BYTES;
180
+ if (isNewDay || isOversized) {
181
+ if (state.stream) {
182
+ await closeStream(state.stream);
183
+ }
184
+ await mkdir(getLogDir(), { recursive: true });
185
+ const filePath = isOversized
186
+ ? nextRolledFilePath(surface, today)
187
+ : dailyFilePath(surface, today);
188
+ const stream = await openStream(filePath);
189
+ state.stream = stream;
190
+ state.date = today;
191
+ // Stat the target file so reopening a same-day file across a process
192
+ // restart still enforces the cap accurately, instead of resetting to 0
193
+ // and silently growing the already-oversized base file further.
194
+ state.sizeBytes = statSizeOrZero(filePath);
195
+ }
196
+ // `resolveStream` only sets `state.stream` to a non-null value above, and
197
+ // this function is the sole place that ever nulls or reassigns it, so the
198
+ // non-null assertion here is safe.
199
+ return state.stream;
200
+ }
201
+ /**
202
+ * Serializes `line` for `surface`: acquires that surface's exclusive queue,
203
+ * resolves (opening/rotating as needed) the current stream, and writes.
204
+ * Resolves once the OS-level write has completed; rejects (never throws
205
+ * synchronously) if the directory/file couldn't be created or the write
206
+ * failed — callers (see `logger.ts`) must handle rejection to honor the
207
+ * "logger never throws" invariant.
208
+ */
209
+ export function writeLogLine(surface, line) {
210
+ return runExclusive(surface, async () => {
211
+ const stream = await resolveStream(surface);
212
+ const buf = Buffer.from(line.endsWith('\n') ? line : `${line}\n`, 'utf8');
213
+ await writeChunk(stream, buf);
214
+ getState(surface).sizeBytes += buf.length;
215
+ });
216
+ }
217
+ // ---------------------------------------------------------------------------
218
+ // Retention sweep
219
+ // ---------------------------------------------------------------------------
220
+ /**
221
+ * Deletes files under the log directory whose mtime is older than
222
+ * `RETENTION_DAYS`. Best-effort: a missing directory or a per-file stat/
223
+ * unlink failure (permissions, a concurrent process already deleted it,
224
+ * etc.) is swallowed rather than thrown — this must never be able to crash
225
+ * module init or take down a caller that awaits it in a test.
226
+ *
227
+ * Exported (not just fired at module init) so tests can await a
228
+ * deterministic run against a temp directory rather than racing the
229
+ * fire-and-forget call below.
230
+ */
231
+ export async function pruneExpiredLogs() {
232
+ const dir = getLogDir();
233
+ try {
234
+ if (!existsSync(dir))
235
+ return;
236
+ const entries = await readdir(dir);
237
+ const cutoff = Date.now() - RETENTION_DAYS * 24 * 60 * 60 * 1000;
238
+ await Promise.all(entries.map(async (name) => {
239
+ const full = join(dir, name);
240
+ try {
241
+ const info = await stat(full);
242
+ if (info.isFile() && info.mtimeMs < cutoff) {
243
+ await unlink(full);
244
+ }
245
+ }
246
+ catch {
247
+ // Best-effort per-file; ignore and move on.
248
+ }
249
+ }));
250
+ }
251
+ catch {
252
+ // Best-effort overall; never throw from module init.
253
+ }
254
+ }
255
+ // Fire-and-forget at module load — async, non-blocking, intentionally not
256
+ // awaited (F2: "unrelated to the active writer"). Skipped under Vitest
257
+ // (`process.env.VITEST` is set automatically by the test runner, not
258
+ // something call sites configure) and via an explicit opt-out, so merely
259
+ // IMPORTING this module — which every `logger.test.ts`/`redact.test.ts` run
260
+ // does transitively — never sweeps the real `~/.skillsmith/logs/` directory
261
+ // as a side effect. Tests call `pruneExpiredLogs()` directly against
262
+ // `SKILLSMITH_LOG_DIR` instead, for a deterministic, awaitable run.
263
+ if (process.env.VITEST !== 'true' && process.env.SKILLSMITH_LOG_DISABLE_STARTUP_SWEEP !== '1') {
264
+ void pruneExpiredLogs();
265
+ }
266
+ // ---------------------------------------------------------------------------
267
+ // Test-only reset
268
+ // ---------------------------------------------------------------------------
269
+ /**
270
+ * Closes any open streams and clears all in-memory state. Test-only — used
271
+ * by `rotation.test.ts` between cases so state from one temp-dir scenario
272
+ * never leaks into the next.
273
+ */
274
+ export async function __resetLoggingStateForTests() {
275
+ const closes = [];
276
+ for (const state of states.values()) {
277
+ if (state.stream)
278
+ closes.push(closeStream(state.stream));
279
+ }
280
+ await Promise.all(closes);
281
+ states.clear();
282
+ queueTails.clear();
283
+ }
284
+ //# sourceMappingURL=rotation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rotation.js","sourceRoot":"","sources":["../../../src/logging/rotation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * SMI-5615: Tests for the per-surface serialized JSONL writer (`rotation.ts`).
3
+ *
4
+ * Covers the plan's P-5 required test ("fire N concurrent large ...
5
+ * writes ... assert every line parses as valid JSON with no
6
+ * interleaved/torn content"), plus daily rollover, size-cap rollover, and
7
+ * the 14-day retention sweep. All tests point `SKILLSMITH_LOG_DIR` at a temp
8
+ * directory — never the real `~/.skillsmith/logs/`.
9
+ */
10
+ export {};
11
+ //# sourceMappingURL=rotation.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rotation.test.d.ts","sourceRoot":"","sources":["../../../src/logging/rotation.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}
@@ -0,0 +1,132 @@
1
+ /**
2
+ * SMI-5615: Tests for the per-surface serialized JSONL writer (`rotation.ts`).
3
+ *
4
+ * Covers the plan's P-5 required test ("fire N concurrent large ...
5
+ * writes ... assert every line parses as valid JSON with no
6
+ * interleaved/torn content"), plus daily rollover, size-cap rollover, and
7
+ * the 14-day retention sweep. All tests point `SKILLSMITH_LOG_DIR` at a temp
8
+ * directory — never the real `~/.skillsmith/logs/`.
9
+ */
10
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
11
+ import { existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, utimesSync, writeFileSync, } from 'node:fs';
12
+ import { tmpdir } from 'node:os';
13
+ import { join } from 'node:path';
14
+ import { __resetLoggingStateForTests, pruneExpiredLogs, writeLogLine } from './rotation.js';
15
+ let tempDir;
16
+ let originalLogDir;
17
+ beforeEach(() => {
18
+ tempDir = mkdtempSync(join(tmpdir(), 'skillsmith-log-rotation-'));
19
+ originalLogDir = process.env.SKILLSMITH_LOG_DIR;
20
+ process.env.SKILLSMITH_LOG_DIR = tempDir;
21
+ });
22
+ afterEach(async () => {
23
+ await __resetLoggingStateForTests();
24
+ if (originalLogDir === undefined) {
25
+ delete process.env.SKILLSMITH_LOG_DIR;
26
+ }
27
+ else {
28
+ process.env.SKILLSMITH_LOG_DIR = originalLogDir;
29
+ }
30
+ vi.useRealTimers();
31
+ rmSync(tempDir, { recursive: true, force: true });
32
+ });
33
+ describe('rotation.ts — write serialization (F2)', () => {
34
+ it('serializes N concurrent large (>PIPE_BUF) writes without interleaving or tearing', async () => {
35
+ const N = 25;
36
+ const PAYLOAD_SIZE = 6000; // > PIPE_BUF (4096 bytes)
37
+ const writes = Array.from({ length: N }, (_, i) => writeLogLine('mcp', JSON.stringify({ id: i, blob: 'x'.repeat(PAYLOAD_SIZE) })));
38
+ await Promise.all(writes);
39
+ const files = readdirSync(tempDir).filter((f) => f.startsWith('skillsmith-mcp-'));
40
+ expect(files).toHaveLength(1);
41
+ const content = readFileSync(join(tempDir, files[0]), 'utf8');
42
+ const lines = content.split('\n').filter((line) => line.length > 0);
43
+ expect(lines).toHaveLength(N);
44
+ const seenIds = new Set();
45
+ for (const line of lines) {
46
+ // JSON.parse throws on a torn/interleaved line — this is the actual
47
+ // no-tearing assertion, not just the id-uniqueness check below.
48
+ const parsed = JSON.parse(line);
49
+ expect(parsed.blob).toHaveLength(PAYLOAD_SIZE);
50
+ seenIds.add(parsed.id);
51
+ }
52
+ expect(seenIds.size).toBe(N);
53
+ });
54
+ it('keeps concurrent writes to different surfaces independent', async () => {
55
+ await Promise.all([
56
+ writeLogLine('mcp', JSON.stringify({ surface: 'mcp' })),
57
+ writeLogLine('cli', JSON.stringify({ surface: 'cli' })),
58
+ writeLogLine('vscode', JSON.stringify({ surface: 'vscode' })),
59
+ ]);
60
+ const files = readdirSync(tempDir);
61
+ expect(files.some((f) => f.startsWith('skillsmith-mcp-'))).toBe(true);
62
+ expect(files.some((f) => f.startsWith('skillsmith-cli-'))).toBe(true);
63
+ expect(files.some((f) => f.startsWith('skillsmith-vscode-'))).toBe(true);
64
+ });
65
+ });
66
+ describe('rotation.ts — daily rollover', () => {
67
+ it('rolls to a new dated file when the calendar date changes', async () => {
68
+ vi.useFakeTimers();
69
+ vi.setSystemTime(new Date('2026-01-01T23:59:00Z'));
70
+ await writeLogLine('cli', JSON.stringify({ day: 1 }));
71
+ vi.setSystemTime(new Date('2026-01-02T00:01:00Z'));
72
+ await writeLogLine('cli', JSON.stringify({ day: 2 }));
73
+ const files = readdirSync(tempDir)
74
+ .filter((f) => f.startsWith('skillsmith-cli-'))
75
+ .sort();
76
+ expect(files).toEqual(['skillsmith-cli-2026-01-01.jsonl', 'skillsmith-cli-2026-01-02.jsonl']);
77
+ const day1 = readFileSync(join(tempDir, 'skillsmith-cli-2026-01-01.jsonl'), 'utf8').trim();
78
+ const day2 = readFileSync(join(tempDir, 'skillsmith-cli-2026-01-02.jsonl'), 'utf8').trim();
79
+ expect(JSON.parse(day1)).toEqual({ day: 1 });
80
+ expect(JSON.parse(day2)).toEqual({ day: 2 });
81
+ });
82
+ });
83
+ describe('rotation.ts — size-cap rollover', () => {
84
+ it('rolls to a .1 continuation file once the current file reaches the ~10MB cap', async () => {
85
+ vi.useFakeTimers();
86
+ vi.setSystemTime(new Date('2026-02-01T12:00:00Z'));
87
+ // First write pushes the base file to (just over) the 10MB cap in one
88
+ // shot — far faster than looping thousands of small writes to get there,
89
+ // and exercises the same in-memory size-tracking path either way.
90
+ const bigPayload = 'x'.repeat(10 * 1024 * 1024);
91
+ await writeLogLine('cli', JSON.stringify({ big: bigPayload }));
92
+ // Second write, same day: resolveStream sees sizeBytes >= cap and rolls
93
+ // to a `.1` continuation file instead of continuing to grow the base file.
94
+ await writeLogLine('cli', JSON.stringify({ rolled: true }));
95
+ const baseName = 'skillsmith-cli-2026-02-01.jsonl';
96
+ expect(existsSync(join(tempDir, `${baseName}.1`))).toBe(true);
97
+ const rolledContent = readFileSync(join(tempDir, `${baseName}.1`), 'utf8').trim();
98
+ expect(JSON.parse(rolledContent)).toEqual({ rolled: true });
99
+ const baseLines = readFileSync(join(tempDir, baseName), 'utf8')
100
+ .split('\n')
101
+ .filter((line) => line.length > 0);
102
+ expect(baseLines).toHaveLength(1);
103
+ }, 15000);
104
+ });
105
+ describe('rotation.ts — retention sweep', () => {
106
+ it('deletes files older than 14 days and keeps recent ones', async () => {
107
+ const oldFile = join(tempDir, 'skillsmith-mcp-2020-01-01.jsonl');
108
+ const recentFile = join(tempDir, 'skillsmith-mcp-2026-01-01.jsonl');
109
+ writeFileSync(oldFile, '{}\n');
110
+ writeFileSync(recentFile, '{}\n');
111
+ const fifteenDaysAgoSec = (Date.now() - 15 * 24 * 60 * 60 * 1000) / 1000;
112
+ const oneDayAgoSec = (Date.now() - 1 * 24 * 60 * 60 * 1000) / 1000;
113
+ utimesSync(oldFile, fifteenDaysAgoSec, fifteenDaysAgoSec);
114
+ utimesSync(recentFile, oneDayAgoSec, oneDayAgoSec);
115
+ await pruneExpiredLogs();
116
+ expect(existsSync(oldFile)).toBe(false);
117
+ expect(existsSync(recentFile)).toBe(true);
118
+ });
119
+ it('does not delete directories, only files', async () => {
120
+ const oldDir = join(tempDir, 'not-a-log-file');
121
+ mkdirSync(oldDir);
122
+ const fifteenDaysAgoSec = (Date.now() - 15 * 24 * 60 * 60 * 1000) / 1000;
123
+ utimesSync(oldDir, fifteenDaysAgoSec, fifteenDaysAgoSec);
124
+ await expect(pruneExpiredLogs()).resolves.toBeUndefined();
125
+ expect(existsSync(oldDir)).toBe(true);
126
+ });
127
+ it('is a no-op (never throws) when the log directory does not exist', async () => {
128
+ process.env.SKILLSMITH_LOG_DIR = join(tempDir, 'does-not-exist');
129
+ await expect(pruneExpiredLogs()).resolves.toBeUndefined();
130
+ });
131
+ });
132
+ //# sourceMappingURL=rotation.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rotation.test.js","sourceRoot":"","sources":["../../../src/logging/rotation.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * SMI-5615: Shared types for the production error-logging module
3
+ * (`packages/core/src/logging/`).
4
+ *
5
+ * Field list and shape verified against
6
+ * docs/internal/implementation/production-error-logging.md §1.
7
+ */
8
+ /** Log severity, ordered `debug < info < warn < error`. */
9
+ export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
10
+ /** Which invocation surface produced a record — one JSONL file per surface. */
11
+ export type Surface = 'mcp' | 'cli' | 'vscode';
12
+ /** Normalized, already-redacted error shape embedded in a `LogRecord`. */
13
+ export interface LogRecordError {
14
+ name: string;
15
+ message: string;
16
+ /** Redacted, capped to the first 20 frames. */
17
+ stack?: string;
18
+ }
19
+ /**
20
+ * One JSON-line record written to
21
+ * `~/.skillsmith/logs/skillsmith-<surface>-<YYYY-MM-DD>.jsonl`.
22
+ *
23
+ * Field order mirrors the plan's listing (ts, level, surface, event, msg,
24
+ * err, correlationId, toolOrCommand, skillId, version, pid) — `logger.ts`
25
+ * constructs records in this order so `JSON.stringify` output (insertion
26
+ * order for string keys) reads consistently on disk.
27
+ */
28
+ export interface LogRecord {
29
+ ts: string;
30
+ level: LogLevel;
31
+ surface: Surface;
32
+ /** Short machine-readable event/category tag. Defaults to `level` when omitted. */
33
+ event: string;
34
+ /** Redacted human-readable message. */
35
+ msg: string;
36
+ err?: LogRecordError;
37
+ correlationId?: string;
38
+ toolOrCommand?: string;
39
+ skillId?: string;
40
+ version: string;
41
+ pid: number;
42
+ /**
43
+ * Additional structured context beyond the plan's core field list —
44
+ * carries forward the old (dead) `mcp-server/src/logger.ts`'s freeform
45
+ * `details` capability so callers don't lose arbitrary context. Redacted
46
+ * via `redactSensitiveObject` like every other field. Omitted entirely
47
+ * when the caller passes no extra keys.
48
+ */
49
+ details?: Record<string, unknown>;
50
+ }
51
+ /**
52
+ * The `details` argument accepted by every `Logger` method. Recognized keys
53
+ * are lifted into their own `LogRecord` fields; anything else is folded into
54
+ * `LogRecord.details` (redacted). Matches the old logger's
55
+ * `(message: string, details?: unknown)` call shape while giving structure to
56
+ * the fields the new record format cares about.
57
+ */
58
+ export interface LogDetails {
59
+ /** Short machine-readable event/category tag for this record. */
60
+ event?: string;
61
+ /** Raw error to normalize into `LogRecord.err` (redacted). */
62
+ err?: unknown;
63
+ /** MCP tool name or CLI command name associated with this record. */
64
+ toolOrCommand?: string;
65
+ /** Skill ID associated with this record, when applicable. */
66
+ skillId?: string;
67
+ [key: string]: unknown;
68
+ }
69
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/logging/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,2DAA2D;AAC3D,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAA;AAE1D,+EAA+E;AAC/E,MAAM,MAAM,OAAO,GAAG,KAAK,GAAG,KAAK,GAAG,QAAQ,CAAA;AAE9C,0EAA0E;AAC1E,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,+CAA+C;IAC/C,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,QAAQ,CAAA;IACf,OAAO,EAAE,OAAO,CAAA;IAChB,mFAAmF;IACnF,KAAK,EAAE,MAAM,CAAA;IACb,uCAAuC;IACvC,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,CAAC,EAAE,cAAc,CAAA;IACpB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,GAAG,EAAE,MAAM,CAAA;IACX;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAClC;AAED;;;;;;GAMG;AACH,MAAM,WAAW,UAAU;IACzB,iEAAiE;IACjE,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,8DAA8D;IAC9D,GAAG,CAAC,EAAE,OAAO,CAAA;IACb,qEAAqE;IACrE,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,6DAA6D;IAC7D,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACvB"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * SMI-5615: Shared types for the production error-logging module
3
+ * (`packages/core/src/logging/`).
4
+ *
5
+ * Field list and shape verified against
6
+ * docs/internal/implementation/production-error-logging.md §1.
7
+ */
8
+ export {};
9
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/logging/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @fileoverview Public barrel for the paywall trigger-state store (SMI-5456
3
+ * Wave 1 Step 5, QD-3). See `store.ts`'s module header for the
4
+ * Wave-1 scope limitation on in-conversation dismissal
5
+ * recording, and `path.ts`'s header for why this module is
6
+ * `paywall-triggers/`, not `triggers/` (a pre-existing,
7
+ * unrelated module owns that name).
8
+ * @module @skillsmith/core/paywall-triggers
9
+ */
10
+ export { TRIGGER_DISMISSAL_THRESHOLD, TRIGGER_MUTE_DAYS, emptyTriggerState, type TriggerId, type TriggerState, } from './types.js';
11
+ export { TRIGGER_STATE_DIR_ENV_VAR, getNudgeCooldownState, getTriggerStateDirForTests, getTriggerStateFilePath, } from './path.js';
12
+ export { canShowTrigger, isTriggerMuted, loadTriggerState, recordImpression, recordTriggerDismissal, } from './store.js';
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/paywall-triggers/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EACL,2BAA2B,EAC3B,iBAAiB,EACjB,iBAAiB,EACjB,KAAK,SAAS,EACd,KAAK,YAAY,GAClB,MAAM,YAAY,CAAA;AAEnB,OAAO,EACL,yBAAyB,EACzB,qBAAqB,EACrB,0BAA0B,EAC1B,uBAAuB,GACxB,MAAM,WAAW,CAAA;AAElB,OAAO,EACL,cAAc,EACd,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,YAAY,CAAA"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @fileoverview Public barrel for the paywall trigger-state store (SMI-5456
3
+ * Wave 1 Step 5, QD-3). See `store.ts`'s module header for the
4
+ * Wave-1 scope limitation on in-conversation dismissal
5
+ * recording, and `path.ts`'s header for why this module is
6
+ * `paywall-triggers/`, not `triggers/` (a pre-existing,
7
+ * unrelated module owns that name).
8
+ * @module @skillsmith/core/paywall-triggers
9
+ */
10
+ export { TRIGGER_DISMISSAL_THRESHOLD, TRIGGER_MUTE_DAYS, emptyTriggerState, } from './types.js';
11
+ export { TRIGGER_STATE_DIR_ENV_VAR, getNudgeCooldownState, getTriggerStateDirForTests, getTriggerStateFilePath, } from './path.js';
12
+ export { canShowTrigger, isTriggerMuted, loadTriggerState, recordImpression, recordTriggerDismissal, } from './store.js';
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/paywall-triggers/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EACL,2BAA2B,EAC3B,iBAAiB,EACjB,iBAAiB,GAGlB,MAAM,YAAY,CAAA;AAEnB,OAAO,EACL,yBAAyB,EACzB,qBAAqB,EACrB,0BAA0B,EAC1B,uBAAuB,GACxB,MAAM,WAAW,CAAA;AAElB,OAAO,EACL,cAAc,EACd,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,YAAY,CAAA"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Trigger-state file layout (SMI-5456 Wave 1 Step 5, QD-3).
3
+ *
4
+ * `~/.skillsmith/paywall-triggers/<triggerId>.json` — one file per trigger,
5
+ * mirroring the per-resource-directory convention already used by
6
+ * `journal/path.ts` (`~/.skillsmith/journal/`) and
7
+ * `telemetry/agent-marker.ts` (`~/.skillsmith/agent-markers/`). Named
8
+ * `paywall-triggers` (not `triggers`) both in the module path and the
9
+ * on-disk directory to avoid any collision with the PRE-EXISTING, unrelated
10
+ * `packages/core/src/triggers/` module (`TriggerDetector`/`ContextScorer` —
11
+ * proactive skill-suggestion detection, nothing to do with PRD §8.1's T1-T4
12
+ * paywall triggers).
13
+ *
14
+ * Format compatibility with the SessionStart hook's nudge cooldown
15
+ * (the per-harness `hooks/<harness>/session-start.sh` script, generated by
16
+ * the — locked for this step — `agent-pack/hooks.ts`): that hook writes a
17
+ * PLAIN epoch-seconds integer to
18
+ * `~/.skillsmith/agent-nudge.state` (`SKILLSMITH_AGENT_NUDGE_STATE`
19
+ * override), because it is self-contained POSIX sh with no JSON tooling
20
+ * available. This module's {@link getNudgeCooldownState} reads that EXACT
21
+ * file/format/override so a future consumer (a report, a diagnostic) can
22
+ * inspect the onboarding-nudge cooldown through the same TS surface as the
23
+ * T1-T4 paywall triggers, without asking the hook to change its wire format.
24
+ * The T1-T4 trigger files themselves are independent, JSON-shaped, and own
25
+ * their own directory — see the module header of `store.ts` for why.
26
+ *
27
+ * @module @skillsmith/core/paywall-triggers/path
28
+ */
29
+ import type { TriggerId } from './types.js';
30
+ /** Env var overriding the trigger-state directory (test isolation). */
31
+ export declare const TRIGGER_STATE_DIR_ENV_VAR = "SKILLSMITH_TRIGGER_STATE_DIR";
32
+ export declare function getTriggerStateFilePath(triggerId: TriggerId): string;
33
+ export declare function getTriggerStateDirForTests(): string;
34
+ /**
35
+ * Read the onboarding SessionStart hook's nudge-cooldown stamp — the SAME
36
+ * file (`~/.skillsmith/agent-nudge.state`, override
37
+ * `SKILLSMITH_AGENT_NUDGE_STATE`) `hooks.ts`'s `renderSessionStartHook`
38
+ * writes a bare epoch-seconds integer into. Read-only: this module never
39
+ * writes this file — that stays the hook's job.
40
+ *
41
+ * @returns the last-nudge epoch-seconds, or null if the file is absent,
42
+ * empty, or not a valid non-negative integer (matches the hook's own
43
+ * tolerant `case "" | *[!0-9]*) last=0` parsing — malformed content is
44
+ * treated as "no prior nudge", never an error).
45
+ */
46
+ export declare function getNudgeCooldownState(): number | null;
47
+ //# sourceMappingURL=path.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path.d.ts","sourceRoot":"","sources":["../../../src/paywall-triggers/path.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAMH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAE3C,uEAAuE;AACvE,eAAO,MAAM,yBAAyB,iCAAiC,CAAA;AAOvE,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,SAAS,GAAG,MAAM,CAEpE;AAED,wBAAgB,0BAA0B,IAAI,MAAM,CAEnD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,GAAG,IAAI,CAcrD"}