@sanity/ailf 0.1.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 (530) hide show
  1. package/README.md +89 -0
  2. package/bin/ailf.js +64 -0
  3. package/canonical/grader-references/README.md +88 -0
  4. package/canonical/grader-references/groq.yaml +234 -0
  5. package/canonical/grader-references/studio-setup.yaml +275 -0
  6. package/canonical/reference-solutions/.gitkeep +1 -0
  7. package/canonical/reference-solutions/frameworks/nuxt.ts +119 -0
  8. package/canonical/reference-solutions/frameworks/remix.tsx +100 -0
  9. package/canonical/reference-solutions/functions/publish-webhook.ts +60 -0
  10. package/canonical/reference-solutions/groq/advanced-filtering.ts +379 -0
  11. package/canonical/reference-solutions/groq/blog-queries.ts +137 -0
  12. package/canonical/reference-solutions/groq/joins-references.ts +300 -0
  13. package/canonical/reference-solutions/nextjs/app-router-integration.tsx +128 -0
  14. package/canonical/reference-solutions/studio-setup/blog-schema.ts +143 -0
  15. package/canonical/reference-solutions/studio-setup/custom-tool.tsx +78 -0
  16. package/canonical/reference-solutions/visual-editing/live-preview.tsx +137 -0
  17. package/canonical/reference-solutions/visual-editing/presentation-nextjs.tsx +130 -0
  18. package/config/airbyte/ai_literacy_framework.connector.yaml +639 -0
  19. package/config/bigquery/README.md +74 -0
  20. package/config/bigquery/views/area_scores.sql +87 -0
  21. package/config/bigquery/views/reports.sql +49 -0
  22. package/config/features.yaml +116 -0
  23. package/config/models.yaml +115 -0
  24. package/config/prompts.yaml +75 -0
  25. package/config/rubrics.yaml +62 -0
  26. package/config/schedules.yaml +43 -0
  27. package/config/sinks.yaml +54 -0
  28. package/config/sources.yaml +51 -0
  29. package/config/thresholds.yaml +49 -0
  30. package/dist/_vendor/ailf-core/examples/index.d.ts +190 -0
  31. package/dist/_vendor/ailf-core/examples/index.js +285 -0
  32. package/dist/_vendor/ailf-core/index.d.ts +17 -0
  33. package/dist/_vendor/ailf-core/index.js +17 -0
  34. package/dist/_vendor/ailf-core/ports/cache-store.d.ts +72 -0
  35. package/dist/_vendor/ailf-core/ports/cache-store.js +17 -0
  36. package/dist/_vendor/ailf-core/ports/config-source.d.ts +33 -0
  37. package/dist/_vendor/ailf-core/ports/config-source.js +15 -0
  38. package/dist/_vendor/ailf-core/ports/context.d.ts +172 -0
  39. package/dist/_vendor/ailf-core/ports/context.js +14 -0
  40. package/dist/_vendor/ailf-core/ports/doc-fetcher.d.ts +131 -0
  41. package/dist/_vendor/ailf-core/ports/doc-fetcher.js +12 -0
  42. package/dist/_vendor/ailf-core/ports/eval-runner.d.ts +24 -0
  43. package/dist/_vendor/ailf-core/ports/eval-runner.js +8 -0
  44. package/dist/_vendor/ailf-core/ports/index.d.ts +15 -0
  45. package/dist/_vendor/ailf-core/ports/index.js +7 -0
  46. package/dist/_vendor/ailf-core/ports/logger.d.ts +36 -0
  47. package/dist/_vendor/ailf-core/ports/logger.js +11 -0
  48. package/dist/_vendor/ailf-core/ports/pipeline-step.d.ts +46 -0
  49. package/dist/_vendor/ailf-core/ports/pipeline-step.js +8 -0
  50. package/dist/_vendor/ailf-core/ports/task-source.d.ts +159 -0
  51. package/dist/_vendor/ailf-core/ports/task-source.js +72 -0
  52. package/dist/_vendor/ailf-core/schemas/callback-payload.d.ts +24 -0
  53. package/dist/_vendor/ailf-core/schemas/callback-payload.js +29 -0
  54. package/dist/_vendor/ailf-core/schemas/eval-config.d.ts +55 -0
  55. package/dist/_vendor/ailf-core/schemas/eval-config.js +78 -0
  56. package/dist/_vendor/ailf-core/schemas/index.d.ts +16 -0
  57. package/dist/_vendor/ailf-core/schemas/index.js +16 -0
  58. package/dist/_vendor/ailf-core/schemas/pipeline-request.d.ts +125 -0
  59. package/dist/_vendor/ailf-core/schemas/pipeline-request.js +67 -0
  60. package/dist/_vendor/ailf-core/schemas/pipeline.d.ts +531 -0
  61. package/dist/_vendor/ailf-core/schemas/pipeline.js +318 -0
  62. package/dist/_vendor/ailf-core/schemas/schedules.d.ts +68 -0
  63. package/dist/_vendor/ailf-core/schemas/schedules.js +74 -0
  64. package/dist/_vendor/ailf-core/schemas/sinks.d.ts +207 -0
  65. package/dist/_vendor/ailf-core/schemas/sinks.js +108 -0
  66. package/dist/_vendor/ailf-core/services/comparison-formatters.d.ts +18 -0
  67. package/dist/_vendor/ailf-core/services/comparison-formatters.js +189 -0
  68. package/dist/_vendor/ailf-core/services/config-helpers.d.ts +41 -0
  69. package/dist/_vendor/ailf-core/services/config-helpers.js +86 -0
  70. package/dist/_vendor/ailf-core/services/index.d.ts +12 -0
  71. package/dist/_vendor/ailf-core/services/index.js +12 -0
  72. package/dist/_vendor/ailf-core/services/scoring.d.ts +49 -0
  73. package/dist/_vendor/ailf-core/services/scoring.js +222 -0
  74. package/dist/_vendor/ailf-core/types/index.d.ts +1082 -0
  75. package/dist/_vendor/ailf-core/types/index.js +21 -0
  76. package/dist/_vendor/ailf-core/types/scoring-input.d.ts +54 -0
  77. package/dist/_vendor/ailf-core/types/scoring-input.js +9 -0
  78. package/dist/_vendor/ailf-shared/dimension-names.d.ts +21 -0
  79. package/dist/_vendor/ailf-shared/dimension-names.js +27 -0
  80. package/dist/_vendor/ailf-shared/document-ref.d.ts +29 -0
  81. package/dist/_vendor/ailf-shared/document-ref.js +1 -0
  82. package/dist/_vendor/ailf-shared/eval-modes.d.ts +12 -0
  83. package/dist/_vendor/ailf-shared/eval-modes.js +8 -0
  84. package/dist/_vendor/ailf-shared/index.d.ts +16 -0
  85. package/dist/_vendor/ailf-shared/index.js +16 -0
  86. package/dist/_vendor/ailf-shared/noise-threshold.d.ts +9 -0
  87. package/dist/_vendor/ailf-shared/noise-threshold.js +9 -0
  88. package/dist/_vendor/ailf-shared/score-grades.d.ts +17 -0
  89. package/dist/_vendor/ailf-shared/score-grades.js +23 -0
  90. package/dist/adapters/cache/content-lake-cache.d.ts +24 -0
  91. package/dist/adapters/cache/content-lake-cache.js +59 -0
  92. package/dist/adapters/cache/filesystem-cache.d.ts +18 -0
  93. package/dist/adapters/cache/filesystem-cache.js +54 -0
  94. package/dist/adapters/cache/index.d.ts +2 -0
  95. package/dist/adapters/cache/index.js +2 -0
  96. package/dist/adapters/config-sources/cli-config-adapter.d.ts +17 -0
  97. package/dist/adapters/config-sources/cli-config-adapter.js +23 -0
  98. package/dist/adapters/config-sources/file-config-adapter.d.ts +26 -0
  99. package/dist/adapters/config-sources/file-config-adapter.js +96 -0
  100. package/dist/adapters/config-sources/index.d.ts +2 -0
  101. package/dist/adapters/config-sources/index.js +2 -0
  102. package/dist/adapters/doc-fetchers/index.d.ts +1 -0
  103. package/dist/adapters/doc-fetchers/index.js +1 -0
  104. package/dist/adapters/doc-fetchers/sanity-doc-fetcher.d.ts +76 -0
  105. package/dist/adapters/doc-fetchers/sanity-doc-fetcher.js +620 -0
  106. package/dist/adapters/eval-runners/index.d.ts +1 -0
  107. package/dist/adapters/eval-runners/index.js +1 -0
  108. package/dist/adapters/eval-runners/promptfoo-eval-adapter.d.ts +14 -0
  109. package/dist/adapters/eval-runners/promptfoo-eval-adapter.js +63 -0
  110. package/dist/adapters/index.d.ts +12 -0
  111. package/dist/adapters/index.js +12 -0
  112. package/dist/adapters/loggers/console-logger.d.ts +22 -0
  113. package/dist/adapters/loggers/console-logger.js +54 -0
  114. package/dist/adapters/loggers/index.d.ts +9 -0
  115. package/dist/adapters/loggers/index.js +9 -0
  116. package/dist/adapters/loggers/json-logger.d.ts +18 -0
  117. package/dist/adapters/loggers/json-logger.js +33 -0
  118. package/dist/adapters/loggers/quiet-logger.d.ts +16 -0
  119. package/dist/adapters/loggers/quiet-logger.js +30 -0
  120. package/dist/adapters/task-sources/composite-task-source.d.ts +20 -0
  121. package/dist/adapters/task-sources/composite-task-source.js +59 -0
  122. package/dist/adapters/task-sources/content-lake-task-source.d.ts +20 -0
  123. package/dist/adapters/task-sources/content-lake-task-source.js +219 -0
  124. package/dist/adapters/task-sources/index.d.ts +7 -0
  125. package/dist/adapters/task-sources/index.js +7 -0
  126. package/dist/adapters/task-sources/repo-schemas.d.ts +245 -0
  127. package/dist/adapters/task-sources/repo-schemas.js +234 -0
  128. package/dist/adapters/task-sources/repo-task-source.d.ts +22 -0
  129. package/dist/adapters/task-sources/repo-task-source.js +104 -0
  130. package/dist/adapters/task-sources/repo-trigger.d.ts +52 -0
  131. package/dist/adapters/task-sources/repo-trigger.js +153 -0
  132. package/dist/adapters/task-sources/repo-validation.d.ts +49 -0
  133. package/dist/adapters/task-sources/repo-validation.js +164 -0
  134. package/dist/adapters/task-sources/yaml-task-source.d.ts +18 -0
  135. package/dist/adapters/task-sources/yaml-task-source.js +136 -0
  136. package/dist/agent-observer/agentic-provider.d.ts +132 -0
  137. package/dist/agent-observer/agentic-provider.js +983 -0
  138. package/dist/agent-observer/classifier.d.ts +62 -0
  139. package/dist/agent-observer/classifier.js +269 -0
  140. package/dist/agent-observer/index.d.ts +7 -0
  141. package/dist/agent-observer/index.js +4 -0
  142. package/dist/agent-observer/pricing.d.ts +35 -0
  143. package/dist/agent-observer/pricing.js +82 -0
  144. package/dist/agent-observer/provider.d.ts +77 -0
  145. package/dist/agent-observer/provider.js +151 -0
  146. package/dist/agent-observer/proxy.d.ts +91 -0
  147. package/dist/agent-observer/proxy.js +321 -0
  148. package/dist/agent-observer/test-imports.d.ts +7 -0
  149. package/dist/agent-observer/test-imports.js +185 -0
  150. package/dist/agent-observer/types.d.ts +137 -0
  151. package/dist/agent-observer/types.js +16 -0
  152. package/dist/assertions/source-isolation.d.ts +72 -0
  153. package/dist/assertions/source-isolation.js +117 -0
  154. package/dist/cli.d.ts +24 -0
  155. package/dist/cli.js +199 -0
  156. package/dist/commands/agent-report.d.ts +5 -0
  157. package/dist/commands/agent-report.js +69 -0
  158. package/dist/commands/baseline.d.ts +9 -0
  159. package/dist/commands/baseline.js +141 -0
  160. package/dist/commands/cache.d.ts +13 -0
  161. package/dist/commands/cache.js +135 -0
  162. package/dist/commands/calculate-scores.d.ts +8 -0
  163. package/dist/commands/calculate-scores.js +48 -0
  164. package/dist/commands/compare.d.ts +8 -0
  165. package/dist/commands/compare.js +120 -0
  166. package/dist/commands/completion.d.ts +18 -0
  167. package/dist/commands/completion.js +260 -0
  168. package/dist/commands/coverage-audit.d.ts +7 -0
  169. package/dist/commands/coverage-audit.js +40 -0
  170. package/dist/commands/discovery-report.d.ts +10 -0
  171. package/dist/commands/discovery-report.js +44 -0
  172. package/dist/commands/eval.d.ts +9 -0
  173. package/dist/commands/eval.js +35 -0
  174. package/dist/commands/explain-handler.d.ts +34 -0
  175. package/dist/commands/explain-handler.js +719 -0
  176. package/dist/commands/fetch-docs.d.ts +8 -0
  177. package/dist/commands/fetch-docs.js +128 -0
  178. package/dist/commands/generate-configs.d.ts +8 -0
  179. package/dist/commands/generate-configs.js +46 -0
  180. package/dist/commands/grader/index.d.ts +11 -0
  181. package/dist/commands/grader/index.js +118 -0
  182. package/dist/commands/init.d.ts +19 -0
  183. package/dist/commands/init.js +150 -0
  184. package/dist/commands/interactive.d.ts +12 -0
  185. package/dist/commands/interactive.js +238 -0
  186. package/dist/commands/lookup-doc.d.ts +15 -0
  187. package/dist/commands/lookup-doc.js +84 -0
  188. package/dist/commands/measure-retrieval.d.ts +5 -0
  189. package/dist/commands/measure-retrieval.js +65 -0
  190. package/dist/commands/pipeline-action.d.ts +71 -0
  191. package/dist/commands/pipeline-action.js +305 -0
  192. package/dist/commands/pipeline.d.ts +62 -0
  193. package/dist/commands/pipeline.js +53 -0
  194. package/dist/commands/pr-comment.d.ts +8 -0
  195. package/dist/commands/pr-comment.js +47 -0
  196. package/dist/commands/publish.d.ts +26 -0
  197. package/dist/commands/publish.js +253 -0
  198. package/dist/commands/readiness-report.d.ts +10 -0
  199. package/dist/commands/readiness-report.js +104 -0
  200. package/dist/commands/shared/options.d.ts +29 -0
  201. package/dist/commands/shared/options.js +57 -0
  202. package/dist/commands/update-quality-scores.d.ts +5 -0
  203. package/dist/commands/update-quality-scores.js +20 -0
  204. package/dist/commands/validate-tasks.d.ts +16 -0
  205. package/dist/commands/validate-tasks.js +93 -0
  206. package/dist/commands/validate.d.ts +9 -0
  207. package/dist/commands/validate.js +73 -0
  208. package/dist/commands/webhook-server.d.ts +5 -0
  209. package/dist/commands/webhook-server.js +30 -0
  210. package/dist/commands/weekly-digest.d.ts +10 -0
  211. package/dist/commands/weekly-digest.js +104 -0
  212. package/dist/composition-root.d.ts +26 -0
  213. package/dist/composition-root.js +107 -0
  214. package/dist/interpolate.d.ts +26 -0
  215. package/dist/interpolate.js +70 -0
  216. package/dist/job-store.d.ts +104 -0
  217. package/dist/job-store.js +188 -0
  218. package/dist/lib/agent-behavior-report.d.ts +8 -0
  219. package/dist/lib/agent-behavior-report.js +185 -0
  220. package/dist/lib/baseline.d.ts +19 -0
  221. package/dist/lib/baseline.js +153 -0
  222. package/dist/lib/calculate-scores.d.ts +23 -0
  223. package/dist/lib/calculate-scores.js +42 -0
  224. package/dist/lib/compare.d.ts +18 -0
  225. package/dist/lib/compare.js +170 -0
  226. package/dist/lib/coverage-audit.d.ts +4 -0
  227. package/dist/lib/coverage-audit.js +42 -0
  228. package/dist/lib/discovery-report.d.ts +13 -0
  229. package/dist/lib/discovery-report.js +57 -0
  230. package/dist/lib/fetch-docs.d.ts +30 -0
  231. package/dist/lib/fetch-docs.js +171 -0
  232. package/dist/lib/generate-configs.d.ts +25 -0
  233. package/dist/lib/generate-configs.js +42 -0
  234. package/dist/lib/grader-api.d.ts +21 -0
  235. package/dist/lib/grader-api.js +34 -0
  236. package/dist/lib/grader-compare.d.ts +19 -0
  237. package/dist/lib/grader-compare.js +91 -0
  238. package/dist/lib/grader-consistency.d.ts +27 -0
  239. package/dist/lib/grader-consistency.js +79 -0
  240. package/dist/lib/grader-sensitivity.d.ts +19 -0
  241. package/dist/lib/grader-sensitivity.js +75 -0
  242. package/dist/lib/grader-validate.d.ts +19 -0
  243. package/dist/lib/grader-validate.js +78 -0
  244. package/dist/lib/measure-retrieval.d.ts +14 -0
  245. package/dist/lib/measure-retrieval.js +71 -0
  246. package/dist/lib/pr-comment.d.ts +16 -0
  247. package/dist/lib/pr-comment.js +28 -0
  248. package/dist/lib/readiness-report.d.ts +13 -0
  249. package/dist/lib/readiness-report.js +108 -0
  250. package/dist/lib/webhook-server.d.ts +11 -0
  251. package/dist/lib/webhook-server.js +24 -0
  252. package/dist/lib/weekly-digest.d.ts +24 -0
  253. package/dist/lib/weekly-digest.js +148 -0
  254. package/dist/orchestration/build-app-context.d.ts +27 -0
  255. package/dist/orchestration/build-app-context.js +81 -0
  256. package/dist/orchestration/build-step-sequence.d.ts +15 -0
  257. package/dist/orchestration/build-step-sequence.js +84 -0
  258. package/dist/orchestration/config-to-source-overrides.d.ts +9 -0
  259. package/dist/orchestration/config-to-source-overrides.js +28 -0
  260. package/dist/orchestration/env-bridge.d.ts +21 -0
  261. package/dist/orchestration/env-bridge.js +66 -0
  262. package/dist/orchestration/index.d.ts +11 -0
  263. package/dist/orchestration/index.js +11 -0
  264. package/dist/orchestration/pipeline-orchestrator.d.ts +24 -0
  265. package/dist/orchestration/pipeline-orchestrator.js +153 -0
  266. package/dist/orchestration/step-runner.d.ts +20 -0
  267. package/dist/orchestration/step-runner.js +88 -0
  268. package/dist/orchestration/steps/calculate-scores-step.d.ts +13 -0
  269. package/dist/orchestration/steps/calculate-scores-step.js +95 -0
  270. package/dist/orchestration/steps/callback-step.d.ts +24 -0
  271. package/dist/orchestration/steps/callback-step.js +76 -0
  272. package/dist/orchestration/steps/compare-step.d.ts +14 -0
  273. package/dist/orchestration/steps/compare-step.js +92 -0
  274. package/dist/orchestration/steps/discovery-report-step.d.ts +13 -0
  275. package/dist/orchestration/steps/discovery-report-step.js +55 -0
  276. package/dist/orchestration/steps/fetch-docs-shell.d.ts +17 -0
  277. package/dist/orchestration/steps/fetch-docs-shell.js +30 -0
  278. package/dist/orchestration/steps/fetch-docs-step.d.ts +14 -0
  279. package/dist/orchestration/steps/fetch-docs-step.js +135 -0
  280. package/dist/orchestration/steps/gap-analysis-step.d.ts +16 -0
  281. package/dist/orchestration/steps/gap-analysis-step.js +136 -0
  282. package/dist/orchestration/steps/generate-configs-step.d.ts +14 -0
  283. package/dist/orchestration/steps/generate-configs-step.js +85 -0
  284. package/dist/orchestration/steps/grader-consistency-step.d.ts +13 -0
  285. package/dist/orchestration/steps/grader-consistency-step.js +64 -0
  286. package/dist/orchestration/steps/index.d.ts +19 -0
  287. package/dist/orchestration/steps/index.js +19 -0
  288. package/dist/orchestration/steps/mirror-repo-tasks-step.d.ts +21 -0
  289. package/dist/orchestration/steps/mirror-repo-tasks-step.js +94 -0
  290. package/dist/orchestration/steps/publish-report-step.d.ts +26 -0
  291. package/dist/orchestration/steps/publish-report-step.js +216 -0
  292. package/dist/orchestration/steps/readiness-step.d.ts +13 -0
  293. package/dist/orchestration/steps/readiness-step.js +91 -0
  294. package/dist/orchestration/steps/report-step.d.ts +12 -0
  295. package/dist/orchestration/steps/report-step.js +49 -0
  296. package/dist/orchestration/steps/run-eval-step.d.ts +17 -0
  297. package/dist/orchestration/steps/run-eval-step.js +195 -0
  298. package/dist/orchestration/steps/validate-step.d.ts +12 -0
  299. package/dist/orchestration/steps/validate-step.js +41 -0
  300. package/dist/pipeline/agent-behavior-report.d.ts +53 -0
  301. package/dist/pipeline/agent-behavior-report.js +132 -0
  302. package/dist/pipeline/attribution.d.ts +47 -0
  303. package/dist/pipeline/attribution.js +226 -0
  304. package/dist/pipeline/baseline.d.ts +37 -0
  305. package/dist/pipeline/baseline.js +141 -0
  306. package/dist/pipeline/cache.d.ts +101 -0
  307. package/dist/pipeline/cache.js +283 -0
  308. package/dist/pipeline/calculate-scores.d.ts +102 -0
  309. package/dist/pipeline/calculate-scores.js +1128 -0
  310. package/dist/pipeline/callback-delivery.d.ts +50 -0
  311. package/dist/pipeline/callback-delivery.js +89 -0
  312. package/dist/pipeline/checks.d.ts +39 -0
  313. package/dist/pipeline/checks.js +280 -0
  314. package/dist/pipeline/classify-url.d.ts +61 -0
  315. package/dist/pipeline/classify-url.js +93 -0
  316. package/dist/pipeline/compare.d.ts +31 -0
  317. package/dist/pipeline/compare.js +208 -0
  318. package/dist/pipeline/coverage-audit.d.ts +39 -0
  319. package/dist/pipeline/coverage-audit.js +165 -0
  320. package/dist/pipeline/degradations.d.ts +85 -0
  321. package/dist/pipeline/degradations.js +242 -0
  322. package/dist/pipeline/discovery-report.d.ts +55 -0
  323. package/dist/pipeline/discovery-report.js +178 -0
  324. package/dist/pipeline/eval-constants.d.ts +68 -0
  325. package/dist/pipeline/eval-constants.js +111 -0
  326. package/dist/pipeline/eval-fingerprint.d.ts +66 -0
  327. package/dist/pipeline/eval-fingerprint.js +175 -0
  328. package/dist/pipeline/expand-tasks.d.ts +220 -0
  329. package/dist/pipeline/expand-tasks.js +421 -0
  330. package/dist/pipeline/failure-modes.d.ts +46 -0
  331. package/dist/pipeline/failure-modes.js +348 -0
  332. package/dist/pipeline/fetch-url-content.d.ts +44 -0
  333. package/dist/pipeline/fetch-url-content.js +93 -0
  334. package/dist/pipeline/gap-analysis.d.ts +48 -0
  335. package/dist/pipeline/gap-analysis.js +231 -0
  336. package/dist/pipeline/generate-configs.d.ts +72 -0
  337. package/dist/pipeline/generate-configs.js +395 -0
  338. package/dist/pipeline/grader-api.d.ts +49 -0
  339. package/dist/pipeline/grader-api.js +200 -0
  340. package/dist/pipeline/grader-compare-runner.d.ts +44 -0
  341. package/dist/pipeline/grader-compare-runner.js +301 -0
  342. package/dist/pipeline/grader-comparison.d.ts +111 -0
  343. package/dist/pipeline/grader-comparison.js +161 -0
  344. package/dist/pipeline/grader-consistency-runner.d.ts +60 -0
  345. package/dist/pipeline/grader-consistency-runner.js +270 -0
  346. package/dist/pipeline/grader-consistency.d.ts +103 -0
  347. package/dist/pipeline/grader-consistency.js +146 -0
  348. package/dist/pipeline/grader-sensitivity-runner.d.ts +40 -0
  349. package/dist/pipeline/grader-sensitivity-runner.js +282 -0
  350. package/dist/pipeline/grader-sensitivity.d.ts +94 -0
  351. package/dist/pipeline/grader-sensitivity.js +144 -0
  352. package/dist/pipeline/grader-validate-runner.d.ts +38 -0
  353. package/dist/pipeline/grader-validate-runner.js +229 -0
  354. package/dist/pipeline/grader-validation.d.ts +107 -0
  355. package/dist/pipeline/grader-validation.js +169 -0
  356. package/dist/pipeline/map-request-to-config.d.ts +19 -0
  357. package/dist/pipeline/map-request-to-config.js +80 -0
  358. package/dist/pipeline/measure-retrieval.d.ts +59 -0
  359. package/dist/pipeline/measure-retrieval.js +111 -0
  360. package/dist/pipeline/mirror-repo-tasks.d.ts +86 -0
  361. package/dist/pipeline/mirror-repo-tasks.js +350 -0
  362. package/dist/pipeline/plan-format.d.ts +33 -0
  363. package/dist/pipeline/plan-format.js +202 -0
  364. package/dist/pipeline/plan.d.ts +169 -0
  365. package/dist/pipeline/plan.js +708 -0
  366. package/dist/pipeline/pr-comment.d.ts +19 -0
  367. package/dist/pipeline/pr-comment.js +502 -0
  368. package/dist/pipeline/probe.d.ts +52 -0
  369. package/dist/pipeline/probe.js +390 -0
  370. package/dist/pipeline/provenance.d.ts +47 -0
  371. package/dist/pipeline/provenance.js +146 -0
  372. package/dist/pipeline/readiness-report.d.ts +87 -0
  373. package/dist/pipeline/readiness-report.js +205 -0
  374. package/dist/pipeline/release-classification.d.ts +54 -0
  375. package/dist/pipeline/release-classification.js +238 -0
  376. package/dist/pipeline/release-report.d.ts +37 -0
  377. package/dist/pipeline/release-report.js +222 -0
  378. package/dist/pipeline/repo-eval-comment.d.ts +37 -0
  379. package/dist/pipeline/repo-eval-comment.js +165 -0
  380. package/dist/pipeline/repo-threshold-evaluator.d.ts +89 -0
  381. package/dist/pipeline/repo-threshold-evaluator.js +162 -0
  382. package/dist/pipeline/resolve-mappings.d.ts +35 -0
  383. package/dist/pipeline/resolve-mappings.js +72 -0
  384. package/dist/pipeline/retrieval-metrics.d.ts +39 -0
  385. package/dist/pipeline/retrieval-metrics.js +136 -0
  386. package/dist/pipeline/reverse-mapping.d.ts +67 -0
  387. package/dist/pipeline/reverse-mapping.js +88 -0
  388. package/dist/pipeline/schemas.d.ts +9 -0
  389. package/dist/pipeline/schemas.js +9 -0
  390. package/dist/pipeline/steps/calculate-scores-step.d.ts +11 -0
  391. package/dist/pipeline/steps/calculate-scores-step.js +89 -0
  392. package/dist/pipeline/steps/compare-step.d.ts +18 -0
  393. package/dist/pipeline/steps/compare-step.js +90 -0
  394. package/dist/pipeline/steps/eval-step.d.ts +53 -0
  395. package/dist/pipeline/steps/eval-step.js +347 -0
  396. package/dist/pipeline/steps/fetch-docs-step.d.ts +11 -0
  397. package/dist/pipeline/steps/fetch-docs-step.js +84 -0
  398. package/dist/pipeline/steps/generate-configs-step.d.ts +11 -0
  399. package/dist/pipeline/steps/generate-configs-step.js +98 -0
  400. package/dist/pipeline/steps/grader-consistency-step.d.ts +21 -0
  401. package/dist/pipeline/steps/grader-consistency-step.js +74 -0
  402. package/dist/pipeline/steps/publish-report-step.d.ts +57 -0
  403. package/dist/pipeline/steps/publish-report-step.js +243 -0
  404. package/dist/pipeline/steps/report-step.d.ts +13 -0
  405. package/dist/pipeline/steps/report-step.js +56 -0
  406. package/dist/pipeline/steps/update-scores-step.d.ts +11 -0
  407. package/dist/pipeline/steps/update-scores-step.js +42 -0
  408. package/dist/pipeline/targeted-loo.d.ts +88 -0
  409. package/dist/pipeline/targeted-loo.js +203 -0
  410. package/dist/pipeline/thresholds.d.ts +27 -0
  411. package/dist/pipeline/thresholds.js +245 -0
  412. package/dist/pipeline/types.d.ts +10 -0
  413. package/dist/pipeline/types.js +10 -0
  414. package/dist/pipeline/validate.d.ts +67 -0
  415. package/dist/pipeline/validate.js +406 -0
  416. package/dist/pipeline/webhook-server.d.ts +37 -0
  417. package/dist/pipeline/webhook-server.js +133 -0
  418. package/dist/report-store.d.ts +84 -0
  419. package/dist/report-store.js +208 -0
  420. package/dist/sanity/client.d.ts +38 -0
  421. package/dist/sanity/client.js +86 -0
  422. package/dist/sanity/portable-text.d.ts +11 -0
  423. package/dist/sanity/portable-text.js +211 -0
  424. package/dist/sanity/queries.d.ts +133 -0
  425. package/dist/sanity/queries.js +300 -0
  426. package/dist/schedules/digest.d.ts +116 -0
  427. package/dist/schedules/digest.js +156 -0
  428. package/dist/schedules/index.d.ts +12 -0
  429. package/dist/schedules/index.js +10 -0
  430. package/dist/schedules/loader.d.ts +31 -0
  431. package/dist/schedules/loader.js +73 -0
  432. package/dist/schedules/schema.d.ts +9 -0
  433. package/dist/schedules/schema.js +9 -0
  434. package/dist/scripts/agent-behavior-report.d.ts +19 -0
  435. package/dist/scripts/agent-behavior-report.js +315 -0
  436. package/dist/scripts/baseline.d.ts +43 -0
  437. package/dist/scripts/baseline.js +267 -0
  438. package/dist/scripts/calculate-scores.d.ts +166 -0
  439. package/dist/scripts/calculate-scores.js +1296 -0
  440. package/dist/scripts/compare.d.ts +22 -0
  441. package/dist/scripts/compare.js +334 -0
  442. package/dist/scripts/coverage-audit.d.ts +44 -0
  443. package/dist/scripts/coverage-audit.js +209 -0
  444. package/dist/scripts/debug-eval.d.ts +19 -0
  445. package/dist/scripts/debug-eval.js +73 -0
  446. package/dist/scripts/discovery-report.d.ts +58 -0
  447. package/dist/scripts/discovery-report.js +250 -0
  448. package/dist/scripts/fetch-docs.d.ts +35 -0
  449. package/dist/scripts/fetch-docs.js +472 -0
  450. package/dist/scripts/generate-configs.d.ts +66 -0
  451. package/dist/scripts/generate-configs.js +459 -0
  452. package/dist/scripts/grader-api.d.ts +27 -0
  453. package/dist/scripts/grader-api.js +206 -0
  454. package/dist/scripts/grader-compare.d.ts +22 -0
  455. package/dist/scripts/grader-compare.js +368 -0
  456. package/dist/scripts/grader-consistency.d.ts +20 -0
  457. package/dist/scripts/grader-consistency.js +313 -0
  458. package/dist/scripts/grader-sensitivity.d.ts +22 -0
  459. package/dist/scripts/grader-sensitivity.js +354 -0
  460. package/dist/scripts/grader-validate.d.ts +19 -0
  461. package/dist/scripts/grader-validate.js +267 -0
  462. package/dist/scripts/measure-retrieval.d.ts +10 -0
  463. package/dist/scripts/measure-retrieval.js +145 -0
  464. package/dist/scripts/migrate-tasks-to-content-lake.d.ts +24 -0
  465. package/dist/scripts/migrate-tasks-to-content-lake.js +327 -0
  466. package/dist/scripts/pipeline.d.ts +76 -0
  467. package/dist/scripts/pipeline.js +1031 -0
  468. package/dist/scripts/pr-comment.d.ts +10 -0
  469. package/dist/scripts/pr-comment.js +510 -0
  470. package/dist/scripts/readiness-report.d.ts +88 -0
  471. package/dist/scripts/readiness-report.js +342 -0
  472. package/dist/scripts/update-quality-scores.d.ts +15 -0
  473. package/dist/scripts/update-quality-scores.js +184 -0
  474. package/dist/scripts/validate-task-sources.d.ts +21 -0
  475. package/dist/scripts/validate-task-sources.js +210 -0
  476. package/dist/scripts/validate.d.ts +13 -0
  477. package/dist/scripts/validate.js +79 -0
  478. package/dist/scripts/webhook-server.d.ts +26 -0
  479. package/dist/scripts/webhook-server.js +147 -0
  480. package/dist/scripts/weekly-digest.d.ts +24 -0
  481. package/dist/scripts/weekly-digest.js +144 -0
  482. package/dist/sinks/bigquery/index.d.ts +131 -0
  483. package/dist/sinks/bigquery/index.js +222 -0
  484. package/dist/sinks/format-slack.d.ts +64 -0
  485. package/dist/sinks/format-slack.js +306 -0
  486. package/dist/sinks/index.d.ts +23 -0
  487. package/dist/sinks/index.js +18 -0
  488. package/dist/sinks/loader.d.ts +18 -0
  489. package/dist/sinks/loader.js +82 -0
  490. package/dist/sinks/retry.d.ts +24 -0
  491. package/dist/sinks/retry.js +52 -0
  492. package/dist/sinks/schema.d.ts +9 -0
  493. package/dist/sinks/schema.js +9 -0
  494. package/dist/sinks/slack/format.d.ts +65 -0
  495. package/dist/sinks/slack/format.js +327 -0
  496. package/dist/sinks/slack/index.d.ts +27 -0
  497. package/dist/sinks/slack/index.js +78 -0
  498. package/dist/sinks/slack-sink.d.ts +27 -0
  499. package/dist/sinks/slack-sink.js +78 -0
  500. package/dist/sinks/types.d.ts +59 -0
  501. package/dist/sinks/types.js +44 -0
  502. package/dist/sinks/webhook/index.d.ts +19 -0
  503. package/dist/sinks/webhook/index.js +50 -0
  504. package/dist/sinks/webhook-sink.d.ts +19 -0
  505. package/dist/sinks/webhook-sink.js +50 -0
  506. package/dist/sources.d.ts +104 -0
  507. package/dist/sources.js +292 -0
  508. package/dist/webhook/budget.d.ts +42 -0
  509. package/dist/webhook/budget.js +60 -0
  510. package/dist/webhook/debounce.d.ts +67 -0
  511. package/dist/webhook/debounce.js +76 -0
  512. package/dist/webhook/dispatch.d.ts +45 -0
  513. package/dist/webhook/dispatch.js +84 -0
  514. package/dist/webhook/eval-request-handler.d.ts +87 -0
  515. package/dist/webhook/eval-request-handler.js +181 -0
  516. package/dist/webhook/handler.d.ts +88 -0
  517. package/dist/webhook/handler.js +203 -0
  518. package/dist/webhook/index.d.ts +17 -0
  519. package/dist/webhook/index.js +12 -0
  520. package/dist/webhook/types.d.ts +109 -0
  521. package/dist/webhook/types.js +10 -0
  522. package/package.json +72 -0
  523. package/tasks/.expanded.agentic.yaml +51 -0
  524. package/tasks/.expanded.yaml +66 -0
  525. package/tasks/frameworks.yaml +98 -0
  526. package/tasks/functions.yaml +51 -0
  527. package/tasks/groq.yaml +216 -0
  528. package/tasks/nextjs-live.yaml +62 -0
  529. package/tasks/studio-setup.yaml +111 -0
  530. package/tasks/visual-editing.yaml +120 -0
@@ -0,0 +1,327 @@
1
+ /**
2
+ * sinks/slack/format.ts
3
+ *
4
+ * Formats evaluation report data into Slack Block Kit structures for the
5
+ * SlackSink. Provides three message formats:
6
+ *
7
+ * - `formatRegressionAlert` — detailed regression notification with
8
+ * per-area dimension breakdowns
9
+ * - `formatScoreSummary` — compact score overview for general reporting
10
+ * - `formatWeeklyDigest` — weekly trend summary for scheduled digests
11
+ *
12
+ * @see docs/design-docs/report-store/sink-architecture.md
13
+ */
14
+ // ---------------------------------------------------------------------------
15
+ // Helpers
16
+ // ---------------------------------------------------------------------------
17
+ /**
18
+ * Format a regression alert for areas that have regressed.
19
+ *
20
+ * Produces a rich Slack message with:
21
+ * - Header with overall score change
22
+ * - Context metadata (mode, source, timestamp, promptfoo link)
23
+ * - Per-area regression details with dimension breakdowns
24
+ * - Brief mentions of improved and unchanged areas
25
+ */
26
+ export function formatRegressionAlert(report) {
27
+ const { comparison, provenance, summary } = report;
28
+ if (!comparison) {
29
+ return {
30
+ blocks: [
31
+ {
32
+ text: { text: "⚠️ No comparison data available", type: "mrkdwn" },
33
+ type: "section",
34
+ },
35
+ ],
36
+ text: "No comparison data available",
37
+ };
38
+ }
39
+ const baselineScore = Math.round(comparison.baseline.overall.avgScore);
40
+ const experimentScore = Math.round(comparison.experiment.overall.avgScore);
41
+ const delta = Math.round(comparison.deltas.overall);
42
+ const blocks = [];
43
+ // Header — emoji + title + overall score change
44
+ blocks.push({
45
+ text: {
46
+ text: `📉 *AI Literacy Score Regression*\n` +
47
+ `Overall: ${baselineScore} → ${experimentScore} (${formatDelta(delta)})`,
48
+ type: "mrkdwn",
49
+ },
50
+ type: "section",
51
+ });
52
+ // Context — mode, source, timestamp, promptfoo link
53
+ const contextElements = [
54
+ { text: `*Mode:* ${provenance.mode}`, type: "mrkdwn" },
55
+ { text: `*Source:* ${provenance.source.name}`, type: "mrkdwn" },
56
+ { text: `*Date:* ${readableDate(summary.timestamp)}`, type: "mrkdwn" },
57
+ ];
58
+ if (provenance.promptfooUrls && provenance.promptfooUrls.length > 0) {
59
+ for (const entry of provenance.promptfooUrls) {
60
+ contextElements.push({
61
+ text: `<${entry.url}|Promptfoo (${entry.mode})>`,
62
+ type: "mrkdwn",
63
+ });
64
+ }
65
+ }
66
+ else if (provenance.promptfooUrl) {
67
+ contextElements.push({
68
+ text: `<${provenance.promptfooUrl}|View in Promptfoo>`,
69
+ type: "mrkdwn",
70
+ });
71
+ }
72
+ blocks.push({ elements: contextElements, type: "context" });
73
+ // Divider
74
+ blocks.push({ type: "divider" });
75
+ // Regressed areas — detailed fields with dimension breakdowns
76
+ const regressedAreas = comparison.areas.filter((a) => a.change === "regressed");
77
+ if (regressedAreas.length > 0) {
78
+ const fields = regressedAreas.map((area) => ({
79
+ text: `*${area.area}:* ${Math.round(area.baseline)} → ` +
80
+ `${Math.round(area.experiment)} (${formatDelta(Math.round(area.delta))})\n` +
81
+ dimensionBreakdown(area.dimensions),
82
+ type: "mrkdwn",
83
+ }));
84
+ blocks.push({
85
+ fields,
86
+ text: {
87
+ text: `*Regressed Areas (${regressedAreas.length})*`,
88
+ type: "mrkdwn",
89
+ },
90
+ type: "section",
91
+ });
92
+ }
93
+ // Improved areas — compact mention
94
+ if (comparison.improved.length > 0) {
95
+ blocks.push({
96
+ text: {
97
+ text: `📈 ${comparison.improved.length} area${comparison.improved.length === 1 ? "" : "s"} improved: ${comparison.improved.join(", ")}`,
98
+ type: "mrkdwn",
99
+ },
100
+ type: "section",
101
+ });
102
+ }
103
+ // Unchanged areas — brief mention
104
+ if (comparison.unchanged.length > 0) {
105
+ blocks.push({
106
+ text: {
107
+ text: `➡️ ${comparison.unchanged.length} area${comparison.unchanged.length === 1 ? "" : "s"} unchanged`,
108
+ type: "mrkdwn",
109
+ },
110
+ type: "section",
111
+ });
112
+ }
113
+ return {
114
+ blocks,
115
+ text: `📉 AI Literacy Score Regression: ${baselineScore} → ${experimentScore} (${formatDelta(delta)})`,
116
+ };
117
+ }
118
+ /**
119
+ * Format a general score summary for Slack reporting.
120
+ *
121
+ * Produces a compact overview with:
122
+ * - Overall score with grade emoji
123
+ * - Per-area score table
124
+ * - Cost summary (if available)
125
+ * - Promptfoo link (if available)
126
+ */
127
+ export function formatScoreSummary(report) {
128
+ const { provenance, summary } = report;
129
+ const overall = Math.round(summary.overall.avgScore);
130
+ const blocks = [];
131
+ // Header — overall score with emoji
132
+ blocks.push({
133
+ text: {
134
+ text: `${gradeEmoji(overall)} *AI Literacy Score: ${overall}*`,
135
+ type: "mrkdwn",
136
+ },
137
+ type: "section",
138
+ });
139
+ // Context — mode, source
140
+ const contextElements = [
141
+ { text: `*Mode:* ${provenance.mode}`, type: "mrkdwn" },
142
+ { text: `*Source:* ${provenance.source.name}`, type: "mrkdwn" },
143
+ { text: `*Date:* ${readableDate(summary.timestamp)}`, type: "mrkdwn" },
144
+ ];
145
+ blocks.push({ elements: contextElements, type: "context" });
146
+ // Divider
147
+ blocks.push({ type: "divider" });
148
+ // Per-area score table as markdown
149
+ const rows = summary.scores
150
+ .map((s) => {
151
+ const emoji = gradeEmoji(s.totalScore);
152
+ return `${emoji} *${s.feature}*: ${Math.round(s.totalScore)} _(T:${Math.round(s.taskCompletion)} · C:${Math.round(s.codeCorrectness)} · D:${Math.round(s.docCoverage)})_`;
153
+ })
154
+ .join("\n");
155
+ blocks.push({
156
+ text: { text: rows, type: "mrkdwn" },
157
+ type: "section",
158
+ });
159
+ // Cost summary
160
+ if (summary.overall.cost) {
161
+ blocks.push({
162
+ text: {
163
+ text: `💰 Total cost: $${summary.overall.cost.total.toFixed(2)} ($${summary.overall.cost.perTest.toFixed(3)}/test)`,
164
+ type: "mrkdwn",
165
+ },
166
+ type: "section",
167
+ });
168
+ }
169
+ // Promptfoo links
170
+ if (provenance.promptfooUrls && provenance.promptfooUrls.length > 0) {
171
+ const links = provenance.promptfooUrls
172
+ .map((e) => `<${e.url}|${e.mode}>`)
173
+ .join(" · ");
174
+ blocks.push({
175
+ text: {
176
+ text: `🔗 View results in Promptfoo: ${links}`,
177
+ type: "mrkdwn",
178
+ },
179
+ type: "section",
180
+ });
181
+ }
182
+ else if (provenance.promptfooUrl) {
183
+ blocks.push({
184
+ text: {
185
+ text: `🔗 <${provenance.promptfooUrl}|View full results in Promptfoo>`,
186
+ type: "mrkdwn",
187
+ },
188
+ type: "section",
189
+ });
190
+ }
191
+ return {
192
+ blocks,
193
+ text: `${gradeEmoji(overall)} AI Literacy Score: ${overall}`,
194
+ };
195
+ }
196
+ /**
197
+ * Format a weekly digest summary for Slack.
198
+ *
199
+ * Produces a summary message covering score trends over a time window:
200
+ * - Header with overall trend direction and score
201
+ * - Per-area trend table with arrows
202
+ * - Lists of improved, regressed, and stable areas
203
+ * - Report count and time window metadata
204
+ */
205
+ export function formatWeeklyDigest(digest) {
206
+ const trendEmoji = digest.overallTrend === "improving"
207
+ ? "📈"
208
+ : digest.overallTrend === "regressing"
209
+ ? "📉"
210
+ : "➡️";
211
+ const blocks = [];
212
+ // Header — overall trend
213
+ blocks.push({
214
+ text: {
215
+ text: `${trendEmoji} *Weekly AI Literacy Digest*\n` +
216
+ `Overall: ${Math.round(digest.overallLatest)} (${formatDelta(Math.round(digest.overallDelta))} this week)`,
217
+ type: "mrkdwn",
218
+ },
219
+ type: "section",
220
+ });
221
+ // Context — time window and report count
222
+ blocks.push({
223
+ elements: [
224
+ {
225
+ text: `*Period:* ${readableDate(digest.lookbackStart)} – ${readableDate(digest.lookbackEnd)}`,
226
+ type: "mrkdwn",
227
+ },
228
+ {
229
+ text: `*Reports:* ${digest.reportCount}`,
230
+ type: "mrkdwn",
231
+ },
232
+ ],
233
+ type: "context",
234
+ });
235
+ blocks.push({ type: "divider" });
236
+ // Per-area trend table
237
+ if (digest.areaTrends.length > 0) {
238
+ const rows = digest.areaTrends
239
+ .map((t) => {
240
+ const arrow = t.trend === "improving" ? "↑" : t.trend === "regressing" ? "↓" : "→";
241
+ const emoji = gradeEmoji(t.lastScore);
242
+ return `${emoji} *${t.area}*: ${Math.round(t.lastScore)} ${arrow} (${formatDelta(Math.round(t.scoreDelta))})`;
243
+ })
244
+ .join("\n");
245
+ blocks.push({
246
+ text: { text: rows, type: "mrkdwn" },
247
+ type: "section",
248
+ });
249
+ }
250
+ // Summary badges
251
+ if (digest.improved.length > 0) {
252
+ blocks.push({
253
+ text: {
254
+ text: `📈 *Improved:* ${digest.improved.join(", ")}`,
255
+ type: "mrkdwn",
256
+ },
257
+ type: "section",
258
+ });
259
+ }
260
+ if (digest.regressed.length > 0) {
261
+ blocks.push({
262
+ text: {
263
+ text: `📉 *Regressed:* ${digest.regressed.join(", ")}`,
264
+ type: "mrkdwn",
265
+ },
266
+ type: "section",
267
+ });
268
+ }
269
+ if (digest.stable.length > 0) {
270
+ blocks.push({
271
+ text: {
272
+ text: `➡️ *Stable:* ${digest.stable.join(", ")}`,
273
+ type: "mrkdwn",
274
+ },
275
+ type: "section",
276
+ });
277
+ }
278
+ // Cost summary if available
279
+ if (digest.totalCost !== undefined) {
280
+ blocks.push({
281
+ text: {
282
+ text: `💰 Total evaluation cost this week: ${digest.totalCost.toFixed(2)}`,
283
+ type: "mrkdwn",
284
+ },
285
+ type: "section",
286
+ });
287
+ }
288
+ return {
289
+ blocks,
290
+ text: `${trendEmoji} Weekly AI Literacy Digest: ${Math.round(digest.overallLatest)} (${formatDelta(Math.round(digest.overallDelta))})`,
291
+ };
292
+ }
293
+ /** Build a dimension breakdown string for an area delta */
294
+ function dimensionBreakdown(dimensions) {
295
+ return [
296
+ `Task: ${formatDelta(dimensions.taskCompletion.delta)}`,
297
+ `Code: ${formatDelta(dimensions.codeCorrectness.delta)}`,
298
+ `Docs: ${formatDelta(dimensions.docCoverage.delta)}`,
299
+ ].join(" · ");
300
+ }
301
+ /** Format a numeric delta with explicit sign: "+4", "-2", or "0" */
302
+ function formatDelta(n) {
303
+ if (n > 0)
304
+ return `+${n}`;
305
+ if (n < 0)
306
+ return `${n}`;
307
+ return "0";
308
+ }
309
+ /** Score-tier emoji: ✅ (≥80), 🟡 (≥70), 🟠 (≥50), 🔴 (<50) */
310
+ function gradeEmoji(score) {
311
+ if (score >= 80)
312
+ return "✅";
313
+ if (score >= 70)
314
+ return "🟡";
315
+ if (score >= 50)
316
+ return "🟠";
317
+ return "🔴";
318
+ }
319
+ /** Format an ISO timestamp into a readable date string */
320
+ function readableDate(iso) {
321
+ const d = new Date(iso);
322
+ return d.toLocaleDateString("en-US", {
323
+ day: "numeric",
324
+ month: "short",
325
+ year: "numeric",
326
+ });
327
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * sinks/slack/index.ts
3
+ *
4
+ * Slack notification sink — posts formatted score change messages to
5
+ * configured Slack channels via incoming webhooks.
6
+ *
7
+ * By default, only posts when regressions are detected (avoids notification
8
+ * fatigue). Set `alwaysPost: true` to receive all reports.
9
+ *
10
+ * @see docs/design-docs/report-store/sink-architecture.md
11
+ * @see docs/design-docs/report-store/notifications.md
12
+ */
13
+ import type { Report, SinkHealthStatus, SinkResult } from "../../pipeline/types.js";
14
+ import type { ReportSink } from "../types.js";
15
+ export interface SlackSinkOptions {
16
+ /** Post all reports, not just regressions (default: false — only regressions) */
17
+ alwaysPost?: boolean;
18
+ }
19
+ export declare class SlackSink implements ReportSink {
20
+ private readonly webhookUrl;
21
+ private readonly channel?;
22
+ private readonly options;
23
+ readonly name = "slack";
24
+ constructor(webhookUrl: string, channel?: string | undefined, options?: SlackSinkOptions);
25
+ healthCheck(): Promise<SinkHealthStatus>;
26
+ publish(report: Report): Promise<SinkResult>;
27
+ }
@@ -0,0 +1,78 @@
1
+ /**
2
+ * sinks/slack/index.ts
3
+ *
4
+ * Slack notification sink — posts formatted score change messages to
5
+ * configured Slack channels via incoming webhooks.
6
+ *
7
+ * By default, only posts when regressions are detected (avoids notification
8
+ * fatigue). Set `alwaysPost: true` to receive all reports.
9
+ *
10
+ * @see docs/design-docs/report-store/sink-architecture.md
11
+ * @see docs/design-docs/report-store/notifications.md
12
+ */
13
+ import { formatRegressionAlert, formatScoreSummary, } from "./format.js";
14
+ export class SlackSink {
15
+ webhookUrl;
16
+ channel;
17
+ options;
18
+ name = "slack";
19
+ constructor(webhookUrl, channel, options = {}) {
20
+ this.webhookUrl = webhookUrl;
21
+ this.channel = channel;
22
+ this.options = options;
23
+ }
24
+ healthCheck() {
25
+ try {
26
+ const url = new URL(this.webhookUrl);
27
+ if (url.protocol !== "https:") {
28
+ return Promise.resolve({
29
+ healthy: false,
30
+ reason: `Webhook URL must use HTTPS, got ${url.protocol}`,
31
+ });
32
+ }
33
+ if (!this.webhookUrl.startsWith("https://hooks.slack.com/")) {
34
+ // Non-standard URL — warn but don't fail (could be a proxy)
35
+ return Promise.resolve({ healthy: true });
36
+ }
37
+ return Promise.resolve({ healthy: true });
38
+ }
39
+ catch {
40
+ return Promise.resolve({
41
+ healthy: false,
42
+ reason: `Invalid webhook URL: ${this.webhookUrl}`,
43
+ });
44
+ }
45
+ }
46
+ async publish(report) {
47
+ const hasRegressions = report.comparison !== undefined && report.comparison.regressed.length > 0;
48
+ let message;
49
+ if (hasRegressions) {
50
+ message = formatRegressionAlert(report);
51
+ }
52
+ else if (this.options.alwaysPost) {
53
+ message = formatScoreSummary(report);
54
+ }
55
+ else {
56
+ return { reason: "No regressions detected", status: "skipped" };
57
+ }
58
+ const body = { ...message };
59
+ if (this.channel) {
60
+ body.channel = this.channel;
61
+ }
62
+ const response = await fetch(this.webhookUrl, {
63
+ body: JSON.stringify(body),
64
+ headers: { "Content-Type": "application/json" },
65
+ method: "POST",
66
+ });
67
+ if (!response.ok) {
68
+ return {
69
+ error: `Slack webhook returned HTTP ${response.status}`,
70
+ status: "failed",
71
+ };
72
+ }
73
+ return {
74
+ detail: hasRegressions ? "regression alert" : "score summary",
75
+ status: "success",
76
+ };
77
+ }
78
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * sinks/slack-sink.ts
3
+ *
4
+ * Slack notification sink — posts formatted score change messages to
5
+ * configured Slack channels via incoming webhooks.
6
+ *
7
+ * By default, only posts when regressions are detected (avoids notification
8
+ * fatigue). Set `alwaysPost: true` to receive all reports.
9
+ *
10
+ * @see docs/design-docs/report-store/sink-architecture.md
11
+ * @see docs/design-docs/report-store/notifications.md
12
+ */
13
+ import type { Report, SinkHealthStatus, SinkResult } from "../pipeline/types.js";
14
+ import type { ReportSink } from "./types.js";
15
+ export interface SlackSinkOptions {
16
+ /** Post all reports, not just regressions (default: false — only regressions) */
17
+ alwaysPost?: boolean;
18
+ }
19
+ export declare class SlackSink implements ReportSink {
20
+ private readonly webhookUrl;
21
+ private readonly channel?;
22
+ private readonly options;
23
+ readonly name = "slack";
24
+ constructor(webhookUrl: string, channel?: string | undefined, options?: SlackSinkOptions);
25
+ healthCheck(): Promise<SinkHealthStatus>;
26
+ publish(report: Report): Promise<SinkResult>;
27
+ }
@@ -0,0 +1,78 @@
1
+ /**
2
+ * sinks/slack-sink.ts
3
+ *
4
+ * Slack notification sink — posts formatted score change messages to
5
+ * configured Slack channels via incoming webhooks.
6
+ *
7
+ * By default, only posts when regressions are detected (avoids notification
8
+ * fatigue). Set `alwaysPost: true` to receive all reports.
9
+ *
10
+ * @see docs/design-docs/report-store/sink-architecture.md
11
+ * @see docs/design-docs/report-store/notifications.md
12
+ */
13
+ import { formatRegressionAlert, formatScoreSummary, } from "./format-slack.js";
14
+ export class SlackSink {
15
+ webhookUrl;
16
+ channel;
17
+ options;
18
+ name = "slack";
19
+ constructor(webhookUrl, channel, options = {}) {
20
+ this.webhookUrl = webhookUrl;
21
+ this.channel = channel;
22
+ this.options = options;
23
+ }
24
+ healthCheck() {
25
+ try {
26
+ const url = new URL(this.webhookUrl);
27
+ if (url.protocol !== "https:") {
28
+ return Promise.resolve({
29
+ healthy: false,
30
+ reason: `Webhook URL must use HTTPS, got ${url.protocol}`,
31
+ });
32
+ }
33
+ if (!this.webhookUrl.startsWith("https://hooks.slack.com/")) {
34
+ // Non-standard URL — warn but don't fail (could be a proxy)
35
+ return Promise.resolve({ healthy: true });
36
+ }
37
+ return Promise.resolve({ healthy: true });
38
+ }
39
+ catch {
40
+ return Promise.resolve({
41
+ healthy: false,
42
+ reason: `Invalid webhook URL: ${this.webhookUrl}`,
43
+ });
44
+ }
45
+ }
46
+ async publish(report) {
47
+ const hasRegressions = report.comparison !== undefined && report.comparison.regressed.length > 0;
48
+ let message;
49
+ if (hasRegressions) {
50
+ message = formatRegressionAlert(report);
51
+ }
52
+ else if (this.options.alwaysPost) {
53
+ message = formatScoreSummary(report);
54
+ }
55
+ else {
56
+ return { reason: "No regressions detected", status: "skipped" };
57
+ }
58
+ const body = { ...message };
59
+ if (this.channel) {
60
+ body.channel = this.channel;
61
+ }
62
+ const response = await fetch(this.webhookUrl, {
63
+ body: JSON.stringify(body),
64
+ headers: { "Content-Type": "application/json" },
65
+ method: "POST",
66
+ });
67
+ if (!response.ok) {
68
+ return {
69
+ error: `Slack webhook returned HTTP ${response.status}`,
70
+ status: "failed",
71
+ };
72
+ }
73
+ return {
74
+ detail: hasRegressions ? "regression alert" : "score summary",
75
+ status: "success",
76
+ };
77
+ }
78
+ }
@@ -0,0 +1,59 @@
1
+ /**
2
+ * sinks/types.ts
3
+ *
4
+ * The ReportSink interface — the contract for all report delivery destinations.
5
+ *
6
+ * Sinks receive published reports and deliver them to external systems
7
+ * (BigQuery, Slack, GitHub, webhooks, etc.). Each sink is self-contained:
8
+ * it handles its own connection, schema mapping, and error handling.
9
+ *
10
+ * Design principle P6: Sinks are fire-and-forget. A sink failure is logged
11
+ * but never blocks the pipeline, the Sanity write, or other sinks.
12
+ *
13
+ * @see docs/design-docs/report-store/sink-architecture.md
14
+ */
15
+ import type { Report, SinkHealthStatus, SinkPayload, SinkResult } from "../pipeline/types.js";
16
+ import type { SinkRouting } from "./schema.js";
17
+ /**
18
+ * A ReportSink receives published reports and delivers them to an
19
+ * external system.
20
+ *
21
+ * Retries are handled by the sink runner (3 retries, exponential backoff)
22
+ * — implementations should not retry internally.
23
+ */
24
+ export interface ReportSink {
25
+ /**
26
+ * Optional health check — called at pipeline start to surface
27
+ * configuration errors early (missing credentials, unreachable endpoint).
28
+ */
29
+ healthCheck?(): Promise<SinkHealthStatus>;
30
+ /** Human-readable name for logging and diagnostics */
31
+ readonly name: string;
32
+ /**
33
+ * Deliver a report to this sink's destination.
34
+ *
35
+ * Called after the report is written to the Sanity Content Lake
36
+ * (system of record). The Sanity document is the source of truth;
37
+ * sinks receive a copy.
38
+ *
39
+ * Implementations may accept either a plain Report (backward compatible)
40
+ * or a SinkPayload (includes threshold violations and severity context).
41
+ *
42
+ * @returns Result indicating success, skip, or failure.
43
+ */
44
+ publish(report: Report | SinkPayload): Promise<SinkResult>;
45
+ /** Optional routing rules from config/sinks.yaml */
46
+ readonly routing?: SinkRouting;
47
+ }
48
+ /**
49
+ * Check whether a sink should receive a delivery based on its routing
50
+ * rules and the payload's severity/comparison data.
51
+ *
52
+ * Returns true (deliver) when:
53
+ * - The sink has no routing config (backward compatible — receives everything)
54
+ * - The payload's maxSeverity matches an enabled routing rule
55
+ * - The payload has regressions and the sink's `regression` rule is enabled
56
+ *
57
+ * @see docs/exec-plans/completed/scenario-matrix-implementation/phase-5-readiness-thresholds.md
58
+ */
59
+ export declare function shouldDeliver(routing: SinkRouting | undefined, payload: SinkPayload): boolean;
@@ -0,0 +1,44 @@
1
+ /**
2
+ * sinks/types.ts
3
+ *
4
+ * The ReportSink interface — the contract for all report delivery destinations.
5
+ *
6
+ * Sinks receive published reports and deliver them to external systems
7
+ * (BigQuery, Slack, GitHub, webhooks, etc.). Each sink is self-contained:
8
+ * it handles its own connection, schema mapping, and error handling.
9
+ *
10
+ * Design principle P6: Sinks are fire-and-forget. A sink failure is logged
11
+ * but never blocks the pipeline, the Sanity write, or other sinks.
12
+ *
13
+ * @see docs/design-docs/report-store/sink-architecture.md
14
+ */
15
+ /**
16
+ * Check whether a sink should receive a delivery based on its routing
17
+ * rules and the payload's severity/comparison data.
18
+ *
19
+ * Returns true (deliver) when:
20
+ * - The sink has no routing config (backward compatible — receives everything)
21
+ * - The payload's maxSeverity matches an enabled routing rule
22
+ * - The payload has regressions and the sink's `regression` rule is enabled
23
+ *
24
+ * @see docs/exec-plans/completed/scenario-matrix-implementation/phase-5-readiness-thresholds.md
25
+ */
26
+ export function shouldDeliver(routing, payload) {
27
+ // No routing config = deliver everything (backward compatible)
28
+ if (!routing)
29
+ return true;
30
+ // Check severity-based routing
31
+ if (payload.maxSeverity !== "none") {
32
+ const severityRule = routing[payload.maxSeverity];
33
+ if (severityRule)
34
+ return true;
35
+ }
36
+ // Check regression routing
37
+ if (routing.regression &&
38
+ payload.comparison &&
39
+ payload.comparison.regressed.length > 0) {
40
+ return true;
41
+ }
42
+ // No matching rule — skip
43
+ return false;
44
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * sinks/webhook/index.ts
3
+ *
4
+ * Generic HTTP webhook sink — POSTs the full report JSON to any endpoint.
5
+ * This is the universal adapter for integrations that don't have a
6
+ * dedicated sink (Airbyte, Zapier, custom services, etc.).
7
+ *
8
+ * @see docs/design-docs/report-store/sink-architecture.md
9
+ */
10
+ import type { Report, SinkHealthStatus, SinkResult } from "../../pipeline/types.js";
11
+ import type { ReportSink } from "../types.js";
12
+ export declare class WebhookSink implements ReportSink {
13
+ private readonly url;
14
+ private readonly headers;
15
+ readonly name: string;
16
+ constructor(url: string, headers?: Record<string, string>);
17
+ healthCheck(): Promise<SinkHealthStatus>;
18
+ publish(report: Report): Promise<SinkResult>;
19
+ }