@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,620 @@
1
+ /**
2
+ * SanityDocFetcher — full adapter for the DocFetcher port.
3
+ *
4
+ * Fetches documentation from the Sanity Content Lake with support for:
5
+ * - Basic slug-based fetching (GROQ → Portable Text → Markdown)
6
+ * - Perspective-aware fetching (content release diffing)
7
+ * - Document overlays (replace/append canonical docs by document ID)
8
+ * - Direct URL fetching (markdown endpoints + content negotiation)
9
+ * - Custom HTTP headers
10
+ * - Document manifest (traceability: _id, _rev, slug, title)
11
+ * - Release impact metadata (added/modified/removed/unchanged)
12
+ *
13
+ * The pipeline step (FetchDocsStep) calls ctx.docFetcher.fetch() and
14
+ * writes the returned metadata to disk for downstream consumption.
15
+ */
16
+ import { mkdirSync, writeFileSync } from "fs";
17
+ import { join } from "path";
18
+ import { canonicalDocRefLabel, isIdRef, isPathRef, isPerspectiveRef, isSlugRef, } from "../../_vendor/ailf-core/index.js";
19
+ import { fetchUrlContent, } from "../../pipeline/fetch-url-content.js";
20
+ import { createPerspectiveClient, createPublishedClient, getSanityClient, } from "../../sanity/client.js";
21
+ import { toMarkdown } from "../../sanity/portable-text.js";
22
+ import { ALL_ARTICLES_QUERY, ALL_FEATURE_AREAS, ARTICLE_BY_ID_QUERY, ARTICLE_BY_SLUG_QUERY, ARTICLE_BY_SLUG_WITH_PERSPECTIVE_QUERY, ARTICLE_SLUG_BY_PATH_QUERY, ARTICLE_SLUG_BY_SECTION_PATH_QUERY, ARTICLES_IN_RELEASE_QUERY, ARTICLES_METADATA_BY_SLUGS_QUERY, FEATURE_AREA_QUERIES, } from "../../sanity/queries.js";
23
+ // ---------------------------------------------------------------------------
24
+ // Helpers
25
+ // ---------------------------------------------------------------------------
26
+ /**
27
+ * Escape `{{` and `}}` so Promptfoo's Nunjucks template engine doesn't
28
+ * try to interpret them as template variables (e.g. Vue `{{ post.title }}`
29
+ * in Nuxt docs would break Nunjucks parsing).
30
+ */
31
+ function escapeNunjucks(text) {
32
+ return text.replace(/\{\{|\}\}/g, (match) => match === "{{" ? '{{ "{{" }}' : '{{ "}}" }}');
33
+ }
34
+ function estimateTokens(text) {
35
+ return Math.ceil(text.length / 4);
36
+ }
37
+ function formatArticle(doc) {
38
+ const sectionLabel = doc.section ? `Section: ${doc.section.title}\n` : "";
39
+ const desc = doc.description ? `${doc.description}\n\n` : "";
40
+ const markdown = toMarkdown(doc.content ?? []);
41
+ return `## ${doc.title}\n\n${sectionLabel}${desc}${markdown}`;
42
+ }
43
+ /**
44
+ * Bridge DocSourceConfig (domain type) to getSanityClient overrides.
45
+ *
46
+ * DocSourceConfig is the port's domain type; the Sanity client expects
47
+ * its own config shape. This bridges the gap.
48
+ */
49
+ function toSanityOverrides(source) {
50
+ if (!source)
51
+ return undefined;
52
+ const overrides = {};
53
+ if (source.dataset)
54
+ overrides.dataset = source.dataset;
55
+ if (source.projectId)
56
+ overrides.projectId = source.projectId;
57
+ return Object.keys(overrides).length > 0 ? overrides : undefined;
58
+ }
59
+ // ---------------------------------------------------------------------------
60
+ // SanityDocFetcher
61
+ // ---------------------------------------------------------------------------
62
+ export class SanityDocFetcher {
63
+ rootDir;
64
+ constructor(rootDir) {
65
+ this.rootDir = rootDir;
66
+ }
67
+ async fetch(tasks, source) {
68
+ // 1. Collect all unique slugs and IDs across every task.
69
+ // ID refs are resolved to slugs via a batch query so the rest of the
70
+ // slug-based pipeline works unchanged.
71
+ const allSlugs = new Set();
72
+ const idRefs = [];
73
+ const pathRefs = [];
74
+ const perspectiveRefs = [];
75
+ for (const task of tasks) {
76
+ for (const ref of task.canonicalDocs) {
77
+ if (isSlugRef(ref)) {
78
+ allSlugs.add(ref.slug);
79
+ }
80
+ else if (isIdRef(ref)) {
81
+ idRefs.push({ id: ref.id, taskId: task.id });
82
+ }
83
+ else if (isPathRef(ref)) {
84
+ pathRefs.push({ path: ref.path, taskId: task.id });
85
+ }
86
+ else if (isPerspectiveRef(ref)) {
87
+ perspectiveRefs.push({
88
+ perspective: ref.perspective,
89
+ taskId: task.id,
90
+ });
91
+ }
92
+ else {
93
+ console.warn(` [warn] Skipping unsupported canonical doc ref: ${canonicalDocRefLabel(ref)}`);
94
+ }
95
+ }
96
+ }
97
+ // Resolve ID refs → slugs via batch query
98
+ const idToSlug = await this.resolveIdRefsToSlugs(idRefs, source);
99
+ for (const slug of idToSlug.values()) {
100
+ allSlugs.add(slug);
101
+ }
102
+ // Resolve path refs → slugs
103
+ const pathToSlug = await this.resolvePathRefsToSlugs(pathRefs, source);
104
+ for (const slug of pathToSlug.values()) {
105
+ allSlugs.add(slug);
106
+ }
107
+ // Resolve perspective refs → slugs (one-to-many: each release expands
108
+ // to all articles versioned within it)
109
+ const perspectiveToSlugs = await this.resolvePerspectiveRefsToSlugs(perspectiveRefs, source);
110
+ for (const slugs of perspectiveToSlugs.values()) {
111
+ for (const slug of slugs) {
112
+ allSlugs.add(slug);
113
+ }
114
+ }
115
+ const metadata = {};
116
+ // 2. Fetch document manifest (traceability metadata)
117
+ const manifest = await this.fetchManifest(allSlugs, source);
118
+ if (manifest.length > 0) {
119
+ metadata.manifest = manifest;
120
+ }
121
+ // 3. Perspective diffing — identify which docs changed in the release
122
+ let releaseImpact;
123
+ if (source?.perspective) {
124
+ releaseImpact = await this.identifyAffectedDocs([...allSlugs], source);
125
+ metadata.releaseImpact = releaseImpact;
126
+ const affected = releaseImpact.added.length +
127
+ releaseImpact.modified.length +
128
+ releaseImpact.removed.length;
129
+ console.log(` Perspective diff: ${affected} of ${allSlugs.size} canonical docs affected`);
130
+ if (releaseImpact.added.length > 0)
131
+ console.log(` Added: ${releaseImpact.added.join(", ")}`);
132
+ if (releaseImpact.modified.length > 0)
133
+ console.log(` Modified: ${releaseImpact.modified.join(", ")}`);
134
+ if (releaseImpact.removed.length > 0)
135
+ console.log(` Removed: ${releaseImpact.removed.join(", ")}`);
136
+ }
137
+ // 4. Document overlay — resolve document IDs against canonical set
138
+ let documentOverlay;
139
+ if (source?.documentIds && source.documentIds.length > 0) {
140
+ console.log(` Resolving ${source.documentIds.length} document ID(s) against canonical set...`);
141
+ documentOverlay = await this.resolveDocumentOverlay(source.documentIds, allSlugs, source);
142
+ const summary = {
143
+ appendedCount: documentOverlay.appendedContent.length,
144
+ documentIds: source.documentIds,
145
+ replacedSlugs: [...documentOverlay.replacements.keys()],
146
+ };
147
+ metadata.documentOverlay = summary;
148
+ console.log(` Document overlay: ${documentOverlay.replacements.size} replacement(s), ${documentOverlay.appendedContent.length} appended`);
149
+ }
150
+ // 5. URL content fetch — fetch direct URLs
151
+ const urlContent = [];
152
+ if (source?.urls && source.urls.length > 0) {
153
+ const urlFetchMeta = [];
154
+ console.log(` Fetching ${source.urls.length} direct URL(s)...`);
155
+ for (const url of source.urls) {
156
+ const result = await fetchUrlContent(url, source.headers);
157
+ urlFetchMeta.push({
158
+ contentLength: result.content?.length,
159
+ error: result.error,
160
+ method: result.method,
161
+ status: result.status,
162
+ url: result.url,
163
+ });
164
+ if (result.content) {
165
+ urlContent.push(result.content);
166
+ const tokens = estimateTokens(result.content);
167
+ console.log(` ✅ ${url} (via ${result.method}, ~${tokens} tokens)`);
168
+ }
169
+ else {
170
+ console.warn(` ⚠️ ${url}: ${result.error}`);
171
+ }
172
+ }
173
+ const fetched = urlFetchMeta.filter((m) => m.method !== "failed");
174
+ const failures = urlFetchMeta.filter((m) => m.method === "failed");
175
+ metadata.urlFetch = {
176
+ failures: failures.map((f) => ({ error: f.error, url: f.url })),
177
+ fetchedUrls: fetched,
178
+ totalFailed: failures.length,
179
+ totalFetched: fetched.length,
180
+ };
181
+ }
182
+ // 6. Fetch canonical docs and assemble per-task contexts
183
+ //
184
+ // Build a per-slug perspective map so each slug is fetched with the
185
+ // right perspective client. Sources:
186
+ // a) release impact diff (added/modified slugs → source perspective)
187
+ // b) perspective ref expansion (expanded slugs → ref's perspective)
188
+ // When both set a perspective for the same slug, the ref-level
189
+ // perspective wins (it's more specific).
190
+ const slugPerspective = new Map();
191
+ // Source-level perspective affects release-impacted slugs
192
+ if (source?.perspective) {
193
+ for (const slug of [
194
+ ...(releaseImpact?.added ?? []),
195
+ ...(releaseImpact?.modified ?? []),
196
+ ]) {
197
+ slugPerspective.set(slug, source.perspective);
198
+ }
199
+ }
200
+ // Perspective ref expansion — each slug gets its ref's perspective
201
+ for (const [perspectiveId, slugs] of perspectiveToSlugs) {
202
+ for (const slug of slugs) {
203
+ slugPerspective.set(slug, perspectiveId);
204
+ }
205
+ }
206
+ const affectedSlugs = new Set(slugPerspective.keys());
207
+ const removedSlugs = new Set(releaseImpact?.removed ?? []);
208
+ const contentBySlug = await this.fetchCanonicalDocs(allSlugs, affectedSlugs, removedSlugs, documentOverlay, source, slugPerspective);
209
+ // 7. Assemble per-task context, write files, build DocContext[]
210
+ const canonicalDir = join(this.rootDir, "contexts", "canonical");
211
+ mkdirSync(canonicalDir, { recursive: true });
212
+ const contexts = tasks.map((task) => {
213
+ const parts = [];
214
+ const slugs = [];
215
+ for (const ref of task.canonicalDocs) {
216
+ // Perspective refs expand to multiple slugs
217
+ if (isPerspectiveRef(ref)) {
218
+ const expanded = perspectiveToSlugs.get(ref.perspective) ?? [];
219
+ for (const slug of expanded) {
220
+ if (removedSlugs.has(slug))
221
+ continue;
222
+ const content = contentBySlug.get(slug) ?? "";
223
+ if (content) {
224
+ parts.push(content);
225
+ slugs.push(slug);
226
+ }
227
+ }
228
+ continue;
229
+ }
230
+ let slug;
231
+ if (isSlugRef(ref)) {
232
+ slug = ref.slug;
233
+ }
234
+ else if (isIdRef(ref)) {
235
+ slug = idToSlug.get(ref.id);
236
+ }
237
+ else if (isPathRef(ref)) {
238
+ slug = pathToSlug.get(ref.path);
239
+ }
240
+ if (!slug)
241
+ continue;
242
+ if (removedSlugs.has(slug))
243
+ continue;
244
+ const content = contentBySlug.get(slug) ?? "";
245
+ if (content) {
246
+ parts.push(content);
247
+ slugs.push(slug);
248
+ }
249
+ }
250
+ // Append extra documents from overlay that didn't match canonical slugs
251
+ if (documentOverlay && documentOverlay.appendedContent.length > 0) {
252
+ parts.push(...documentOverlay.appendedContent);
253
+ }
254
+ // Append URL-fetched content
255
+ if (urlContent.length > 0) {
256
+ parts.push(...urlContent);
257
+ }
258
+ const combined = escapeNunjucks(parts.join("\n\n---\n\n"));
259
+ const contextPath = join(canonicalDir, `${task.id}.md`);
260
+ writeFileSync(contextPath, combined, "utf-8");
261
+ return {
262
+ taskId: task.id,
263
+ content: combined,
264
+ slugs,
265
+ tokenCount: estimateTokens(combined),
266
+ };
267
+ });
268
+ const hasMetadata = Object.keys(metadata).length > 0;
269
+ return {
270
+ contexts,
271
+ ...(hasMetadata ? { metadata } : {}),
272
+ };
273
+ }
274
+ // -----------------------------------------------------------------------
275
+ // Private: Fetch document manifest
276
+ // -----------------------------------------------------------------------
277
+ async fetchManifest(allSlugs, source) {
278
+ const client = source?.perspective
279
+ ? createPerspectiveClient(source.perspective, source)
280
+ : getSanityClient(toSanityOverrides(source));
281
+ const allMetadata = await client.fetch(ARTICLES_METADATA_BY_SLUGS_QUERY, { slugs: [...allSlugs] });
282
+ return allMetadata
283
+ .map((m) => ({ _id: m._id, _rev: m._rev, slug: m.slug, title: m.title }))
284
+ .sort((a, b) => a.slug.localeCompare(b.slug));
285
+ }
286
+ // -----------------------------------------------------------------------
287
+ // Private: Resolve ID refs to slugs
288
+ // -----------------------------------------------------------------------
289
+ /**
290
+ * Batch-resolve document ID refs to their article slugs.
291
+ *
292
+ * This bridges IdDocRef entries into the slug-based fetch pipeline.
293
+ * Articles are queried by _id and their slugs are returned for use
294
+ * in the existing slug-based content map.
295
+ */
296
+ async resolveIdRefsToSlugs(idRefs, source) {
297
+ const result = new Map();
298
+ if (idRefs.length === 0)
299
+ return result;
300
+ const uniqueIds = [...new Set(idRefs.map((r) => r.id))];
301
+ const client = source?.perspective
302
+ ? createPerspectiveClient(source.perspective, source)
303
+ : getSanityClient(toSanityOverrides(source));
304
+ // Batch query: fetch slug for each document ID
305
+ const articles = await client.fetch(`*[_type == "article" && _id in $ids] { _id, "slug": slug.current }`, { ids: uniqueIds });
306
+ const idToSlugMap = new Map(articles.map((a) => [a._id, a.slug]));
307
+ for (const { id, taskId } of idRefs) {
308
+ const slug = idToSlugMap.get(id);
309
+ if (slug) {
310
+ result.set(id, slug);
311
+ }
312
+ else {
313
+ console.warn(` [warn] No article found for document ID "${id}" (referenced by task "${taskId}")`);
314
+ }
315
+ }
316
+ if (result.size > 0) {
317
+ console.log(` Resolved ${result.size} document ID ref(s) to slugs`);
318
+ }
319
+ return result;
320
+ }
321
+ // -----------------------------------------------------------------------
322
+ // Private: Resolve path refs to slugs
323
+ // -----------------------------------------------------------------------
324
+ /**
325
+ * Resolve path-based canonical doc references to their article slugs.
326
+ *
327
+ * Handles two path formats:
328
+ * - Simple path: "webhooks" → resolves as slug lookup
329
+ * - Section-qualified path: "content-lake/webhooks" → matches section + slug
330
+ *
331
+ * @see docs/design-docs/canonical-doc-resolution.md
332
+ */
333
+ async resolvePathRefsToSlugs(pathRefs, source) {
334
+ const result = new Map();
335
+ if (pathRefs.length === 0)
336
+ return result;
337
+ const client = source?.perspective
338
+ ? createPerspectiveClient(source.perspective, source)
339
+ : getSanityClient(toSanityOverrides(source));
340
+ for (const { path, taskId } of pathRefs) {
341
+ const segments = path.split("/").filter(Boolean);
342
+ const articleSlug = segments[segments.length - 1];
343
+ const sectionSlug = segments.length > 1 ? segments.slice(0, -1).join("/") : undefined;
344
+ let article;
345
+ if (sectionSlug) {
346
+ // Section-qualified path: disambiguate by section
347
+ article = await client.fetch(ARTICLE_SLUG_BY_SECTION_PATH_QUERY, {
348
+ articleSlug,
349
+ sectionSlug,
350
+ });
351
+ if (!article) {
352
+ // Fallback: try without section qualifier (section slug might differ)
353
+ article = await client.fetch(ARTICLE_SLUG_BY_PATH_QUERY, { slug: articleSlug });
354
+ if (article) {
355
+ console.warn(` [warn] Path "${path}" section "${sectionSlug}" didn't match (article found in section "${article.sectionSlug ?? "unknown"}")`);
356
+ }
357
+ }
358
+ }
359
+ else {
360
+ // Simple path: resolve by slug directly
361
+ article = await client.fetch(ARTICLE_SLUG_BY_PATH_QUERY, { slug: articleSlug });
362
+ }
363
+ if (article) {
364
+ result.set(path, article.slug);
365
+ }
366
+ else {
367
+ console.warn(` [warn] No article found for path "${path}" (referenced by task "${taskId}")`);
368
+ }
369
+ }
370
+ if (result.size > 0) {
371
+ console.log(` Resolved ${result.size} path ref(s) to slugs`);
372
+ }
373
+ return result;
374
+ }
375
+ // -----------------------------------------------------------------------
376
+ // Private: Resolve perspective refs to slugs (one-to-many)
377
+ // -----------------------------------------------------------------------
378
+ /**
379
+ * Expand perspective canonical doc refs to the article slugs within
380
+ * each content release.
381
+ *
382
+ * Each perspective ref resolves to ALL article documents versioned in
383
+ * that release. This is the one-to-many expansion described in the
384
+ * canonical-doc-resolution design doc.
385
+ *
386
+ * The perspective value from the ref is used as both the release ID
387
+ * for the versioned document query AND the client perspective for
388
+ * fetching content. If a source-level perspective is also set, the
389
+ * ref-level perspective takes precedence for its own resolution.
390
+ *
391
+ * @see docs/design-docs/canonical-doc-resolution.md
392
+ */
393
+ async resolvePerspectiveRefsToSlugs(perspectiveRefs, source) {
394
+ const result = new Map();
395
+ if (perspectiveRefs.length === 0)
396
+ return result;
397
+ // Deduplicate by perspective ID (multiple tasks may reference the same release)
398
+ const uniquePerspectives = [
399
+ ...new Set(perspectiveRefs.map((r) => r.perspective)),
400
+ ];
401
+ for (const perspectiveId of uniquePerspectives) {
402
+ // Create a client with this specific perspective so versioned docs are visible
403
+ const client = createPerspectiveClient(perspectiveId, source);
404
+ const articles = await client.fetch(ARTICLES_IN_RELEASE_QUERY, { releaseId: perspectiveId });
405
+ if (articles.length === 0) {
406
+ const taskIds = perspectiveRefs
407
+ .filter((r) => r.perspective === perspectiveId)
408
+ .map((r) => r.taskId);
409
+ console.warn(` [warn] No articles found in release "${perspectiveId}" (referenced by task(s): ${taskIds.join(", ")})`);
410
+ result.set(perspectiveId, []);
411
+ continue;
412
+ }
413
+ const slugs = articles
414
+ .map((a) => a.slug)
415
+ .filter((s) => Boolean(s));
416
+ result.set(perspectiveId, slugs);
417
+ console.log(` Expanded perspective "${perspectiveId}" → ${slugs.length} article(s): ${slugs.join(", ")}`);
418
+ }
419
+ return result;
420
+ }
421
+ // -----------------------------------------------------------------------
422
+ // Private: Perspective diffing
423
+ // -----------------------------------------------------------------------
424
+ async identifyAffectedDocs(canonicalSlugs, source) {
425
+ if (!source.perspective) {
426
+ return {
427
+ added: [],
428
+ modified: [],
429
+ removed: [],
430
+ unchanged: [...canonicalSlugs],
431
+ };
432
+ }
433
+ const publishedClient = createPublishedClient(source);
434
+ const perspectiveClient = createPerspectiveClient(source.perspective, source);
435
+ const [publishedMeta, perspectiveMeta] = await Promise.all([
436
+ publishedClient.fetch(ARTICLES_METADATA_BY_SLUGS_QUERY, { slugs: canonicalSlugs }),
437
+ perspectiveClient.fetch(ARTICLES_METADATA_BY_SLUGS_QUERY, { slugs: canonicalSlugs }),
438
+ ]);
439
+ const publishedMap = new Map(publishedMeta.map((d) => [d.slug, d]));
440
+ const perspectiveMap = new Map(perspectiveMeta.map((d) => [d.slug, d]));
441
+ const added = [];
442
+ const modified = [];
443
+ const removed = [];
444
+ const unchanged = [];
445
+ for (const slug of canonicalSlugs) {
446
+ const pub = publishedMap.get(slug);
447
+ const persp = perspectiveMap.get(slug);
448
+ if (!pub && persp) {
449
+ added.push(slug);
450
+ }
451
+ else if (pub && !persp) {
452
+ removed.push(slug);
453
+ }
454
+ else if (pub && persp && pub._rev !== persp._rev) {
455
+ modified.push(slug);
456
+ }
457
+ else {
458
+ unchanged.push(slug);
459
+ }
460
+ }
461
+ return { added, modified, removed, unchanged };
462
+ }
463
+ // -----------------------------------------------------------------------
464
+ // Private: Document overlay
465
+ // -----------------------------------------------------------------------
466
+ async resolveDocumentOverlay(documentIds, canonicalSlugs, source) {
467
+ const overlay = {
468
+ appendedContent: [],
469
+ replacements: new Map(),
470
+ };
471
+ if (documentIds.length === 0)
472
+ return overlay;
473
+ const results = await Promise.all(documentIds.map(async (id) => {
474
+ const doc = await this.fetchArticleById(id, source);
475
+ return { doc, id };
476
+ }));
477
+ for (const { doc, id } of results) {
478
+ if (!doc) {
479
+ console.warn(` [warn] No article found for document ID "${id}"`);
480
+ continue;
481
+ }
482
+ const content = formatArticle(doc);
483
+ if (!content)
484
+ continue;
485
+ if (doc.slug && canonicalSlugs.has(doc.slug)) {
486
+ overlay.replacements.set(doc.slug, content);
487
+ console.log(` 📄 Document ${id} → replaces canonical doc "${doc.slug}"`);
488
+ }
489
+ else {
490
+ overlay.appendedContent.push(content);
491
+ const slugInfo = doc.slug ? ` (slug: "${doc.slug}")` : "";
492
+ console.log(` 📄 Document ${id} → appended as additional context${slugInfo}`);
493
+ }
494
+ }
495
+ return overlay;
496
+ }
497
+ // -----------------------------------------------------------------------
498
+ // Private: Fetch individual articles
499
+ // -----------------------------------------------------------------------
500
+ async fetchArticleById(id, source) {
501
+ const client = source.perspective
502
+ ? createPerspectiveClient(source.perspective, source)
503
+ : getSanityClient(toSanityOverrides(source));
504
+ return client.fetch(ARTICLE_BY_ID_QUERY, { id });
505
+ }
506
+ async fetchArticleBySlug(slug) {
507
+ const client = getSanityClient();
508
+ const doc = await client.fetch(ARTICLE_BY_SLUG_QUERY, { slug });
509
+ if (!doc) {
510
+ console.warn(` [warn] No article found for slug "${slug}"`);
511
+ return "";
512
+ }
513
+ return formatArticle(doc);
514
+ }
515
+ async fetchArticleBySlugWithPerspective(slug, source) {
516
+ if (!source.perspective) {
517
+ return this.fetchArticleBySlug(slug);
518
+ }
519
+ const client = createPerspectiveClient(source.perspective, source);
520
+ const doc = await client.fetch(ARTICLE_BY_SLUG_WITH_PERSPECTIVE_QUERY, { slug });
521
+ if (!doc) {
522
+ console.warn(` [warn] No article found for slug "${slug}" in perspective "${source.perspective}"`);
523
+ return "";
524
+ }
525
+ return formatArticle(doc);
526
+ }
527
+ // -----------------------------------------------------------------------
528
+ // Private: Fetch all canonical docs with perspective/overlay awareness
529
+ // -----------------------------------------------------------------------
530
+ async fetchCanonicalDocs(allSlugs, affectedSlugs, removedSlugs, overlay, source, slugPerspective) {
531
+ const contentBySlug = new Map();
532
+ for (const slug of allSlugs) {
533
+ if (removedSlugs.has(slug))
534
+ continue;
535
+ // Check if this slug has a document overlay replacement
536
+ if (overlay?.replacements.has(slug)) {
537
+ console.log(` Fetching: ${slug} (from document overlay)`);
538
+ contentBySlug.set(slug, overlay.replacements.get(slug));
539
+ }
540
+ else if (affectedSlugs.has(slug)) {
541
+ // Use the per-slug perspective when available; fall back to
542
+ // source-level perspective. This ensures perspective-ref-expanded
543
+ // slugs are fetched from their specific release even when no
544
+ // source-level --sanity-perspective is set.
545
+ const perspective = slugPerspective?.get(slug) ?? source?.perspective;
546
+ if (perspective && source) {
547
+ const perspectiveSource = { ...source, perspective };
548
+ console.log(` Fetching: ${slug} (from perspective: ${perspective})`);
549
+ const content = await this.fetchArticleBySlugWithPerspective(slug, perspectiveSource);
550
+ contentBySlug.set(slug, content);
551
+ }
552
+ else {
553
+ // No perspective available — fetch from published
554
+ console.log(` Fetching: ${slug}`);
555
+ const content = await this.fetchArticleBySlug(slug);
556
+ contentBySlug.set(slug, content);
557
+ }
558
+ }
559
+ else {
560
+ console.log(` Fetching: ${slug}`);
561
+ const content = await this.fetchArticleBySlug(slug);
562
+ contentBySlug.set(slug, content);
563
+ }
564
+ }
565
+ return contentBySlug;
566
+ }
567
+ // -----------------------------------------------------------------------
568
+ // Public non-port methods — opt-in CLI features
569
+ // -----------------------------------------------------------------------
570
+ /**
571
+ * Generate feature-area context files (one per GROQ feature area query).
572
+ *
573
+ * This is NOT part of the DocFetcher port — it's an opt-in CLI feature
574
+ * used by `ailf fetch-docs --include-feature-areas`.
575
+ */
576
+ async fetchFeatureAreaContexts(source) {
577
+ const client = getSanityClient(toSanityOverrides(source), source);
578
+ const contextsDir = join(this.rootDir, "contexts");
579
+ mkdirSync(contextsDir, { recursive: true });
580
+ console.log("Generating feature-area contexts...\n");
581
+ for (const feature of ALL_FEATURE_AREAS) {
582
+ const query = FEATURE_AREA_QUERIES[feature];
583
+ const docs = await client.fetch(query);
584
+ if (docs.length === 0) {
585
+ console.warn(` [warn] No articles found for "${feature}"`);
586
+ continue;
587
+ }
588
+ const combined = docs.map(formatArticle).join("\n\n---\n\n");
589
+ const outPath = join(contextsDir, `${feature}.md`);
590
+ writeFileSync(outPath, escapeNunjucks(combined), "utf-8");
591
+ console.log(` ${feature}: ${docs.length} articles, ~${estimateTokens(combined)} tokens`);
592
+ }
593
+ }
594
+ /**
595
+ * Generate a full corpus context file (all articles in one markdown file).
596
+ *
597
+ * This is NOT part of the DocFetcher port — it's an opt-in CLI feature
598
+ * used by `ailf fetch-docs --include-corpus`.
599
+ */
600
+ async fetchFullCorpus(source) {
601
+ const client = getSanityClient(toSanityOverrides(source), source);
602
+ const baseUrl = source?.baseUrl ?? "https://www.sanity.io/docs";
603
+ console.log("\nGenerating full corpus...");
604
+ const docs = await client.fetch(ALL_ARTICLES_QUERY);
605
+ const corpus = docs
606
+ .map((d) => {
607
+ const markdown = toMarkdown(d.content ?? []);
608
+ return (`## ${d.title}\n\n` +
609
+ // oxlint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- empty string title should fall back to "General"
610
+ `Section: ${d.section?.title || "General"}\n` +
611
+ `URL: ${baseUrl}/${d.slug}\n\n` +
612
+ markdown);
613
+ })
614
+ .join("\n\n---\n\n");
615
+ const outDir = join(this.rootDir, "contexts");
616
+ mkdirSync(outDir, { recursive: true });
617
+ writeFileSync(join(outDir, "full-corpus.md"), escapeNunjucks(corpus), "utf-8");
618
+ console.log(` full-corpus.md: ${docs.length} articles, ~${estimateTokens(corpus)} tokens`);
619
+ }
620
+ }
@@ -0,0 +1 @@
1
+ export { PromptfooEvalAdapter } from "./promptfoo-eval-adapter.js";
@@ -0,0 +1 @@
1
+ export { PromptfooEvalAdapter } from "./promptfoo-eval-adapter.js";
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Adapter: Run evaluation via Promptfoo CLI subprocess.
3
+ *
4
+ * This wraps the current execSync-based eval execution behind the
5
+ * EvalRunner port interface, enabling mock-based testing of the
6
+ * pipeline orchestrator.
7
+ */
8
+ import type { EvalRunConfig, EvalRunner, StepResult } from "../../_vendor/ailf-core/index.d.ts";
9
+ export declare class PromptfooEvalAdapter implements EvalRunner {
10
+ private readonly rootDir;
11
+ constructor(rootDir: string);
12
+ run(config: EvalRunConfig): Promise<StepResult>;
13
+ extractShareUrl(outputPath: string): string | undefined;
14
+ }