@probelabs/visor 0.1.106 → 0.1.111

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 +71 -2
  2. package/action.yml +1 -1
  3. package/defaults/code-refiner.yaml +114 -0
  4. package/defaults/{.visor.yaml → code-review.yaml} +35 -226
  5. package/defaults/override.yaml +52 -0
  6. package/defaults/task-refinement.yaml +624 -0
  7. package/defaults/visor.tests.yaml +685 -0
  8. package/defaults/visor.yaml +483 -0
  9. package/dist/action-cli-bridge.d.ts +11 -82
  10. package/dist/action-cli-bridge.d.ts.map +1 -1
  11. package/dist/ai-review-service.d.ts +28 -9
  12. package/dist/ai-review-service.d.ts.map +1 -1
  13. package/dist/check-execution-engine.d.ts +19 -331
  14. package/dist/check-execution-engine.d.ts.map +1 -1
  15. package/dist/cli-main.d.ts.map +1 -1
  16. package/dist/cli.d.ts +0 -1
  17. package/dist/cli.d.ts.map +1 -1
  18. package/dist/config.d.ts +16 -0
  19. package/dist/config.d.ts.map +1 -1
  20. package/dist/cron-scheduler.d.ts +3 -3
  21. package/dist/cron-scheduler.d.ts.map +1 -1
  22. package/dist/debug-visualizer/ws-server.d.ts +7 -1
  23. package/dist/debug-visualizer/ws-server.d.ts.map +1 -1
  24. package/dist/defaults/code-refiner.yaml +114 -0
  25. package/dist/defaults/{.visor.yaml → code-review.yaml} +35 -226
  26. package/dist/defaults/override.yaml +52 -0
  27. package/dist/defaults/task-refinement.yaml +624 -0
  28. package/dist/defaults/visor.tests.yaml +685 -0
  29. package/dist/defaults/visor.yaml +483 -0
  30. package/dist/docs/DEPLOYMENT.md +118 -0
  31. package/dist/docs/GITHUB_CHECKS.md +280 -0
  32. package/dist/docs/NPM_USAGE.md +208 -0
  33. package/dist/docs/action-reference.md +19 -0
  34. package/dist/docs/advanced-ai.md +237 -0
  35. package/dist/docs/ai-configuration.md +535 -0
  36. package/dist/docs/ai-custom-tools-usage.md +261 -0
  37. package/dist/docs/ai-custom-tools.md +392 -0
  38. package/dist/docs/author-permissions.md +610 -0
  39. package/dist/docs/bot-transports-rfc.md +23 -0
  40. package/dist/docs/ci-cli-mode.md +34 -0
  41. package/dist/docs/claude-code.md +74 -0
  42. package/dist/docs/command-provider.md +559 -0
  43. package/dist/docs/commands.md +8 -0
  44. package/dist/docs/configuration.md +324 -0
  45. package/dist/docs/custom-tools.md +424 -0
  46. package/dist/docs/dashboards/README.md +23 -0
  47. package/dist/docs/dashboards/grafana-visor-diagrams.json +20 -0
  48. package/dist/docs/dashboards/grafana-visor-overview.json +33 -0
  49. package/dist/docs/debug-visualizer-progress.md +572 -0
  50. package/dist/docs/debug-visualizer-rfc.md +691 -0
  51. package/dist/docs/debug-visualizer.md +114 -0
  52. package/dist/docs/debugging.md +636 -0
  53. package/dist/docs/default-output-schema.md +28 -0
  54. package/dist/docs/dependencies.md +369 -0
  55. package/dist/docs/dev-playbook.md +9 -0
  56. package/dist/docs/engine-pause-resume-rfc.md +192 -0
  57. package/dist/docs/engine-state-machine-plan.md +333 -0
  58. package/dist/docs/event-driven-github-integration-rfc.md +743 -0
  59. package/dist/docs/event-triggers.md +292 -0
  60. package/dist/docs/execution-statistics-rfc.md +290 -0
  61. package/dist/docs/fact-validator-gap-analysis.md +178 -0
  62. package/dist/docs/fact-validator-implementation-plan.md +1235 -0
  63. package/dist/docs/fail-if.md +95 -0
  64. package/dist/docs/failure-conditions-implementation.md +271 -0
  65. package/dist/docs/failure-conditions-schema.md +173 -0
  66. package/dist/docs/failure-routing-rfc.md +193 -0
  67. package/dist/docs/failure-routing.md +507 -0
  68. package/dist/docs/foreach-dependency-propagation.md +473 -0
  69. package/dist/docs/github-ops.md +89 -0
  70. package/dist/docs/goto-forward-run-plan.md +113 -0
  71. package/dist/docs/guides/criticality-modes.md +332 -0
  72. package/dist/docs/guides/fault-management-and-contracts.md +738 -0
  73. package/dist/docs/guides/workflow-style-guide.md +224 -0
  74. package/dist/docs/http.md +299 -0
  75. package/dist/docs/human-input-provider.md +372 -0
  76. package/dist/docs/lifecycle-hooks.md +253 -0
  77. package/dist/docs/limits.md +64 -0
  78. package/dist/docs/liquid-templates.md +490 -0
  79. package/dist/docs/loop-routing-refactor.md +89 -0
  80. package/dist/docs/mcp-provider.md +557 -0
  81. package/dist/docs/mcp.md +124 -0
  82. package/dist/docs/memory.md +903 -0
  83. package/dist/docs/observability.md +12 -0
  84. package/dist/docs/output-formats.md +20 -0
  85. package/dist/docs/output-formatting.md +29 -0
  86. package/dist/docs/output-history.md +383 -0
  87. package/dist/docs/performance.md +6 -0
  88. package/dist/docs/pluggable.md +124 -0
  89. package/dist/docs/proposals/snapshot-scope-execution.md +236 -0
  90. package/dist/docs/providers/git-checkout.md +589 -0
  91. package/dist/docs/recipes.md +474 -0
  92. package/dist/docs/rfc/git-checkout-step.md +601 -0
  93. package/dist/docs/rfc/on_init-hook.md +1294 -0
  94. package/dist/docs/rfc/workspace-isolation.md +216 -0
  95. package/dist/docs/roadmap/criticality-implementation-tasks.md +92 -0
  96. package/dist/docs/router-patterns.md +339 -0
  97. package/dist/docs/schema-next-pr.md +10 -0
  98. package/dist/docs/schema-templates.md +68 -0
  99. package/dist/docs/script.md +34 -0
  100. package/dist/docs/sdk.md +222 -0
  101. package/dist/docs/security.md +7 -0
  102. package/dist/docs/suppressions.md +89 -0
  103. package/dist/docs/tag-filtering.md +258 -0
  104. package/dist/docs/telemetry-setup.md +119 -0
  105. package/dist/docs/telemetry-tracing-rfc.md +275 -0
  106. package/dist/docs/test-framework-rfc.md +680 -0
  107. package/dist/docs/testing/assertions.md +85 -0
  108. package/dist/docs/testing/ci.md +44 -0
  109. package/dist/docs/testing/cli.md +41 -0
  110. package/dist/docs/testing/cookbook.md +172 -0
  111. package/dist/docs/testing/dsl-reference.md +199 -0
  112. package/dist/docs/testing/fixtures-and-mocks.md +91 -0
  113. package/dist/docs/testing/flows.md +92 -0
  114. package/dist/docs/testing/getting-started.md +93 -0
  115. package/dist/docs/testing/troubleshooting.md +55 -0
  116. package/dist/docs/timeouts.md +50 -0
  117. package/dist/docs/troubleshooting.md +7 -0
  118. package/dist/docs/visor-sdk-rfc.md +186 -0
  119. package/dist/docs/workflows.md +569 -0
  120. package/dist/engine/on-finish/orchestrator.d.ts +19 -0
  121. package/dist/engine/on-finish/orchestrator.d.ts.map +1 -0
  122. package/dist/engine/on-finish/utils.d.ts +44 -0
  123. package/dist/engine/on-finish/utils.d.ts.map +1 -0
  124. package/dist/event-bus/event-bus.d.ts +13 -0
  125. package/dist/event-bus/event-bus.d.ts.map +1 -0
  126. package/dist/event-bus/types.d.ts +71 -0
  127. package/dist/event-bus/types.d.ts.map +1 -0
  128. package/dist/examples/.claude/agents/code-reviewer.md +69 -0
  129. package/dist/examples/.mcp.json +34 -0
  130. package/dist/examples/CALCULATOR-SDK.md +364 -0
  131. package/dist/examples/README.md +384 -0
  132. package/dist/examples/ai-custom-tools-example.yaml +206 -0
  133. package/dist/examples/ai-custom-tools-simple.yaml +76 -0
  134. package/dist/examples/ai-retry-fallback-config.yaml +180 -0
  135. package/dist/examples/ai-with-bash.yaml +126 -0
  136. package/dist/examples/ai-with-mcp.yaml +82 -0
  137. package/dist/examples/basic-human-input.yaml +15 -0
  138. package/dist/examples/bedrock-config.yaml +77 -0
  139. package/dist/examples/calculator-config.yaml +133 -0
  140. package/dist/examples/calculator-json-output-guide.md +311 -0
  141. package/dist/examples/calculator-sdk-automated.ts +340 -0
  142. package/dist/examples/calculator-sdk-example.ts +275 -0
  143. package/dist/examples/calculator-sdk-json.ts +331 -0
  144. package/dist/examples/calculator-sdk-real.ts +374 -0
  145. package/dist/examples/calculator-sdk-test.ts +148 -0
  146. package/dist/examples/claude-code-config.yaml +191 -0
  147. package/dist/examples/cron-webhook-config.yaml +215 -0
  148. package/dist/examples/custom-template.liquid +57 -0
  149. package/dist/examples/custom-tools-example.yaml +281 -0
  150. package/dist/examples/enhanced-config.yaml +165 -0
  151. package/dist/examples/environments/visor.base.yaml +92 -0
  152. package/dist/examples/environments/visor.dev.yaml +33 -0
  153. package/dist/examples/environments/visor.prod.yaml +95 -0
  154. package/dist/examples/environments/visor.staging.yaml +46 -0
  155. package/dist/examples/fact-validator.yaml +361 -0
  156. package/dist/examples/fail-if-simple.yaml +90 -0
  157. package/dist/examples/failure-conditions-advanced.yaml +136 -0
  158. package/dist/examples/failure-conditions-basic.yaml +48 -0
  159. package/dist/examples/failure-conditions-github-style.yaml +119 -0
  160. package/dist/examples/failure-conditions-migration.yaml +74 -0
  161. package/dist/examples/for-loop-example.yaml +176 -0
  162. package/dist/examples/forEach-example.yaml +120 -0
  163. package/dist/examples/git-checkout-basic.yaml +32 -0
  164. package/dist/examples/git-checkout-compare.yaml +59 -0
  165. package/dist/examples/git-checkout-cross-repo.yaml +76 -0
  166. package/dist/examples/github-workflow-with-tags.yml +163 -0
  167. package/dist/examples/http-integration-config.yaml +240 -0
  168. package/dist/examples/https-server-config.yaml +209 -0
  169. package/dist/examples/human-input-example.yaml +63 -0
  170. package/dist/examples/if-conditions.yaml +173 -0
  171. package/dist/examples/jira-simple-example.yaml +56 -0
  172. package/dist/examples/jira-single-issue-workflow.yaml +166 -0
  173. package/dist/examples/jira-workflow-mcp.yaml +182 -0
  174. package/dist/examples/mcp/analyzer.py +119 -0
  175. package/dist/examples/mcp-provider-example.yaml +301 -0
  176. package/dist/examples/memory-counter.yaml +99 -0
  177. package/dist/examples/memory-error-collection.yaml +104 -0
  178. package/dist/examples/memory-exec-js.yaml +247 -0
  179. package/dist/examples/memory-namespace-isolation.yaml +184 -0
  180. package/dist/examples/memory-retry-counter.yaml +65 -0
  181. package/dist/examples/memory-state-machine.yaml +170 -0
  182. package/dist/examples/on-init-import-demo.yaml +179 -0
  183. package/dist/examples/outputs-raw-basic.yaml +26 -0
  184. package/dist/examples/project-with-tools.yaml +174 -0
  185. package/dist/examples/prompts/architecture-analysis.liquid +116 -0
  186. package/dist/examples/prompts/security-comprehensive.liquid +107 -0
  187. package/dist/examples/quick-start-tags.yaml +53 -0
  188. package/dist/examples/reusable-tools.yaml +92 -0
  189. package/dist/examples/reusable-workflows.yaml +88 -0
  190. package/dist/examples/routing-basic.yaml +35 -0
  191. package/dist/examples/routing-dynamic-js.yaml +46 -0
  192. package/dist/examples/routing-foreach.yaml +34 -0
  193. package/dist/examples/routing-goto-event.yaml +34 -0
  194. package/dist/examples/routing-on-success.yaml +25 -0
  195. package/dist/examples/run-calculator-demo.sh +71 -0
  196. package/dist/examples/sdk-basic.mjs +10 -0
  197. package/dist/examples/sdk-cjs.cjs +10 -0
  198. package/dist/examples/sdk-comprehensive.mjs +175 -0
  199. package/dist/examples/sdk-manual-config.mjs +65 -0
  200. package/dist/examples/sdk-typescript.js +81 -0
  201. package/dist/examples/sdk-typescript.ts +92 -0
  202. package/dist/examples/session-reuse-config.yaml +151 -0
  203. package/dist/examples/session-reuse-self.yaml +81 -0
  204. package/dist/examples/slack-simple-chat.yaml +775 -0
  205. package/dist/examples/templates/security-report.liquid +137 -0
  206. package/dist/examples/tools-library.yaml +281 -0
  207. package/dist/examples/transform-example.yaml +199 -0
  208. package/dist/examples/visor-with-tags.yaml +198 -0
  209. package/dist/examples/webhook-pipeline-config.yaml +218 -0
  210. package/dist/examples/workflows/calculator-workflow.yaml +163 -0
  211. package/dist/examples/workflows/code-quality.yaml +222 -0
  212. package/dist/examples/workflows/quick-pr-check.yaml +90 -0
  213. package/dist/examples/workflows/workflow-composition-example.yaml +130 -0
  214. package/dist/failure-condition-evaluator.d.ts +3 -0
  215. package/dist/failure-condition-evaluator.d.ts.map +1 -1
  216. package/dist/frontends/github-frontend.d.ts +58 -0
  217. package/dist/frontends/github-frontend.d.ts.map +1 -0
  218. package/dist/frontends/host.d.ts +47 -0
  219. package/dist/frontends/host.d.ts.map +1 -0
  220. package/dist/frontends/ndjson-sink.d.ts +12 -0
  221. package/dist/frontends/ndjson-sink.d.ts.map +1 -0
  222. package/dist/frontends/slack-frontend.d.ts +58 -0
  223. package/dist/frontends/slack-frontend.d.ts.map +1 -0
  224. package/dist/generated/config-schema.d.ts +967 -57
  225. package/dist/generated/config-schema.d.ts.map +1 -1
  226. package/dist/generated/config-schema.json +1033 -56
  227. package/dist/github-check-service.d.ts +4 -6
  228. package/dist/github-check-service.d.ts.map +1 -1
  229. package/dist/github-comments.d.ts +2 -4
  230. package/dist/github-comments.d.ts.map +1 -1
  231. package/dist/index.d.ts.map +1 -1
  232. package/dist/index.js +134327 -99004
  233. package/dist/liquid-extensions.d.ts.map +1 -1
  234. package/dist/logger.d.ts +2 -0
  235. package/dist/logger.d.ts.map +1 -1
  236. package/dist/memory-store.d.ts +6 -0
  237. package/dist/memory-store.d.ts.map +1 -1
  238. package/dist/output/assistant-json/template.liquid +0 -0
  239. package/dist/output/traces/run-2026-01-20T19-22-58-043Z.ndjson +138 -0
  240. package/dist/output/traces/run-2026-01-20T19-23-52-175Z.ndjson +1067 -0
  241. package/dist/output-formatters.d.ts +1 -1
  242. package/dist/output-formatters.d.ts.map +1 -1
  243. package/dist/providers/ai-check-provider.d.ts +12 -0
  244. package/dist/providers/ai-check-provider.d.ts.map +1 -1
  245. package/dist/providers/check-provider-registry.d.ts +6 -0
  246. package/dist/providers/check-provider-registry.d.ts.map +1 -1
  247. package/dist/providers/check-provider.interface.d.ts +43 -1
  248. package/dist/providers/check-provider.interface.d.ts.map +1 -1
  249. package/dist/providers/claude-code-check-provider.d.ts.map +1 -1
  250. package/dist/providers/command-check-provider.d.ts +1 -1
  251. package/dist/providers/command-check-provider.d.ts.map +1 -1
  252. package/dist/providers/custom-tool-executor.d.ts +61 -0
  253. package/dist/providers/custom-tool-executor.d.ts.map +1 -0
  254. package/dist/providers/git-checkout-provider.d.ts +25 -0
  255. package/dist/providers/git-checkout-provider.d.ts.map +1 -0
  256. package/dist/providers/github-ops-provider.d.ts.map +1 -1
  257. package/dist/providers/http-client-provider.d.ts +4 -4
  258. package/dist/providers/http-client-provider.d.ts.map +1 -1
  259. package/dist/providers/human-input-check-provider.d.ts +5 -0
  260. package/dist/providers/human-input-check-provider.d.ts.map +1 -1
  261. package/dist/providers/index.d.ts +1 -0
  262. package/dist/providers/index.d.ts.map +1 -1
  263. package/dist/providers/log-check-provider.d.ts +2 -5
  264. package/dist/providers/log-check-provider.d.ts.map +1 -1
  265. package/dist/providers/mcp-check-provider.d.ts +10 -4
  266. package/dist/providers/mcp-check-provider.d.ts.map +1 -1
  267. package/dist/providers/mcp-custom-sse-server.d.ts +66 -0
  268. package/dist/providers/mcp-custom-sse-server.d.ts.map +1 -0
  269. package/dist/providers/memory-check-provider.d.ts +2 -8
  270. package/dist/providers/memory-check-provider.d.ts.map +1 -1
  271. package/dist/providers/script-check-provider.d.ts +25 -0
  272. package/dist/providers/script-check-provider.d.ts.map +1 -0
  273. package/dist/providers/workflow-check-provider.d.ts +56 -0
  274. package/dist/providers/workflow-check-provider.d.ts.map +1 -0
  275. package/dist/reviewer.d.ts +2 -1
  276. package/dist/reviewer.d.ts.map +1 -1
  277. package/dist/sdk/check-provider-registry-534KL5HT.mjs +27 -0
  278. package/dist/sdk/chunk-23L3QRYX.mjs +16872 -0
  279. package/dist/sdk/chunk-23L3QRYX.mjs.map +1 -0
  280. package/dist/sdk/{chunk-TUTOLSFV.mjs → chunk-3OMWVM6J.mjs} +11 -1
  281. package/dist/sdk/chunk-3OMWVM6J.mjs.map +1 -0
  282. package/dist/sdk/chunk-7UK3NIIT.mjs +482 -0
  283. package/dist/sdk/chunk-7UK3NIIT.mjs.map +1 -0
  284. package/dist/sdk/chunk-AGIZJ4UZ.mjs +173 -0
  285. package/dist/sdk/chunk-AGIZJ4UZ.mjs.map +1 -0
  286. package/dist/sdk/chunk-AIVFBIS4.mjs +1371 -0
  287. package/dist/sdk/chunk-AIVFBIS4.mjs.map +1 -0
  288. package/dist/sdk/chunk-AK6BVWIT.mjs +426 -0
  289. package/dist/sdk/chunk-AK6BVWIT.mjs.map +1 -0
  290. package/dist/sdk/chunk-AUT26LHW.mjs +139 -0
  291. package/dist/sdk/chunk-AUT26LHW.mjs.map +1 -0
  292. package/dist/sdk/chunk-BOVFH3LI.mjs +232 -0
  293. package/dist/sdk/chunk-BOVFH3LI.mjs.map +1 -0
  294. package/dist/sdk/chunk-CNX7V5JK.mjs +89 -0
  295. package/dist/sdk/chunk-CNX7V5JK.mjs.map +1 -0
  296. package/dist/sdk/chunk-HTOKWMPO.mjs +157 -0
  297. package/dist/sdk/chunk-HTOKWMPO.mjs.map +1 -0
  298. package/dist/sdk/chunk-NAW3DB3I.mjs +197 -0
  299. package/dist/sdk/chunk-NAW3DB3I.mjs.map +1 -0
  300. package/dist/sdk/chunk-O5EZDNYL.mjs +274 -0
  301. package/dist/sdk/chunk-O5EZDNYL.mjs.map +1 -0
  302. package/dist/sdk/chunk-QR7MOMJH.mjs +558 -0
  303. package/dist/sdk/chunk-QR7MOMJH.mjs.map +1 -0
  304. package/dist/sdk/chunk-QY2XYPEV.mjs +3556 -0
  305. package/dist/sdk/chunk-QY2XYPEV.mjs.map +1 -0
  306. package/dist/sdk/chunk-S2RUE2RG.mjs +145 -0
  307. package/dist/sdk/chunk-S2RUE2RG.mjs.map +1 -0
  308. package/dist/sdk/chunk-SIWNBRTK.mjs +800 -0
  309. package/dist/sdk/chunk-SIWNBRTK.mjs.map +1 -0
  310. package/dist/sdk/chunk-YSN4G6CI.mjs +146 -0
  311. package/dist/sdk/chunk-YSN4G6CI.mjs.map +1 -0
  312. package/dist/sdk/chunk-ZYAUYXSW.mjs +206 -0
  313. package/dist/sdk/chunk-ZYAUYXSW.mjs.map +1 -0
  314. package/dist/sdk/command-executor-TYUV6HUS.mjs +14 -0
  315. package/dist/sdk/config-YNC2EOOT.mjs +16 -0
  316. package/dist/sdk/config-merger-PX3WIT57.mjs +10 -0
  317. package/dist/sdk/event-bus-5BEVPQ6T.mjs +35 -0
  318. package/dist/sdk/event-bus-5BEVPQ6T.mjs.map +1 -0
  319. package/dist/sdk/failure-condition-evaluator-YGTF2GHG.mjs +17 -0
  320. package/dist/sdk/git-repository-analyzer-HJC4MYW4.mjs +458 -0
  321. package/dist/sdk/git-repository-analyzer-HJC4MYW4.mjs.map +1 -0
  322. package/dist/sdk/github-frontend-SIAEOCON.mjs +1420 -0
  323. package/dist/sdk/github-frontend-SIAEOCON.mjs.map +1 -0
  324. package/dist/sdk/host-DXUYTNMU.mjs +52 -0
  325. package/dist/sdk/host-DXUYTNMU.mjs.map +1 -0
  326. package/dist/sdk/{liquid-extensions-KVL4MKRH.mjs → liquid-extensions-PKWCKK7E.mjs} +8 -2
  327. package/dist/sdk/memory-store-XGBB7LX7.mjs +12 -0
  328. package/dist/sdk/memory-store-XGBB7LX7.mjs.map +1 -0
  329. package/dist/sdk/metrics-7PP3EJUH.mjs +29 -0
  330. package/dist/sdk/metrics-7PP3EJUH.mjs.map +1 -0
  331. package/dist/sdk/ndjson-sink-B4V4NTAQ.mjs +44 -0
  332. package/dist/sdk/ndjson-sink-B4V4NTAQ.mjs.map +1 -0
  333. package/dist/sdk/prompt-state-YRJY6QAL.mjs +16 -0
  334. package/dist/sdk/prompt-state-YRJY6QAL.mjs.map +1 -0
  335. package/dist/sdk/renderer-schema-LPKN5UJS.mjs +51 -0
  336. package/dist/sdk/renderer-schema-LPKN5UJS.mjs.map +1 -0
  337. package/dist/sdk/routing-6N45MJ4F.mjs +24 -0
  338. package/dist/sdk/routing-6N45MJ4F.mjs.map +1 -0
  339. package/dist/sdk/sdk.d.mts +541 -22
  340. package/dist/sdk/sdk.d.ts +541 -22
  341. package/dist/sdk/sdk.js +27963 -16505
  342. package/dist/sdk/sdk.js.map +1 -1
  343. package/dist/sdk/sdk.mjs +1116 -2169
  344. package/dist/sdk/sdk.mjs.map +1 -1
  345. package/dist/sdk/session-registry-4E6YRQ77.mjs +10 -0
  346. package/dist/sdk/session-registry-4E6YRQ77.mjs.map +1 -0
  347. package/dist/sdk/slack-frontend-BVKW3GD5.mjs +735 -0
  348. package/dist/sdk/slack-frontend-BVKW3GD5.mjs.map +1 -0
  349. package/dist/sdk/trace-helpers-VP6QYVBX.mjs +23 -0
  350. package/dist/sdk/trace-helpers-VP6QYVBX.mjs.map +1 -0
  351. package/dist/sdk/{tracer-init-WC75N5NW.mjs → tracer-init-GSLPPLCD.mjs} +2 -2
  352. package/dist/sdk/tracer-init-GSLPPLCD.mjs.map +1 -0
  353. package/dist/sdk/workflow-registry-R6KSACFR.mjs +12 -0
  354. package/dist/sdk/workflow-registry-R6KSACFR.mjs.map +1 -0
  355. package/dist/sdk.d.ts.map +1 -1
  356. package/dist/slack/adapter.d.ts +36 -0
  357. package/dist/slack/adapter.d.ts.map +1 -0
  358. package/dist/slack/cache-prewarmer.d.ts +31 -0
  359. package/dist/slack/cache-prewarmer.d.ts.map +1 -0
  360. package/dist/slack/client.d.ts +77 -0
  361. package/dist/slack/client.d.ts.map +1 -0
  362. package/dist/slack/markdown.d.ts +45 -0
  363. package/dist/slack/markdown.d.ts.map +1 -0
  364. package/dist/slack/prompt-state.d.ts +33 -0
  365. package/dist/slack/prompt-state.d.ts.map +1 -0
  366. package/dist/slack/rate-limiter.d.ts +56 -0
  367. package/dist/slack/rate-limiter.d.ts.map +1 -0
  368. package/dist/slack/signature.d.ts +2 -0
  369. package/dist/slack/signature.d.ts.map +1 -0
  370. package/dist/slack/socket-runner.d.ts +42 -0
  371. package/dist/slack/socket-runner.d.ts.map +1 -0
  372. package/dist/slack/thread-cache.d.ts +51 -0
  373. package/dist/slack/thread-cache.d.ts.map +1 -0
  374. package/dist/snapshot-store.d.ts +59 -0
  375. package/dist/snapshot-store.d.ts.map +1 -0
  376. package/dist/state-machine/context/build-engine-context.d.ts +17 -0
  377. package/dist/state-machine/context/build-engine-context.d.ts.map +1 -0
  378. package/dist/state-machine/dispatch/dependency-gating.d.ts +12 -0
  379. package/dist/state-machine/dispatch/dependency-gating.d.ts.map +1 -0
  380. package/dist/state-machine/dispatch/execution-invoker.d.ts +14 -0
  381. package/dist/state-machine/dispatch/execution-invoker.d.ts.map +1 -0
  382. package/dist/state-machine/dispatch/foreach-processor.d.ts +8 -0
  383. package/dist/state-machine/dispatch/foreach-processor.d.ts.map +1 -0
  384. package/dist/state-machine/dispatch/history-snapshot.d.ts +8 -0
  385. package/dist/state-machine/dispatch/history-snapshot.d.ts.map +1 -0
  386. package/dist/state-machine/dispatch/on-init-handlers.d.ts +43 -0
  387. package/dist/state-machine/dispatch/on-init-handlers.d.ts.map +1 -0
  388. package/dist/state-machine/dispatch/renderer-schema.d.ts +8 -0
  389. package/dist/state-machine/dispatch/renderer-schema.d.ts.map +1 -0
  390. package/dist/state-machine/dispatch/stats-manager.d.ts +15 -0
  391. package/dist/state-machine/dispatch/stats-manager.d.ts.map +1 -0
  392. package/dist/state-machine/dispatch/template-renderer.d.ts +7 -0
  393. package/dist/state-machine/dispatch/template-renderer.d.ts.map +1 -0
  394. package/dist/state-machine/execution/summary.d.ts +8 -0
  395. package/dist/state-machine/execution/summary.d.ts.map +1 -0
  396. package/dist/state-machine/runner.d.ts +79 -0
  397. package/dist/state-machine/runner.d.ts.map +1 -0
  398. package/dist/state-machine/states/check-running.d.ts +14 -0
  399. package/dist/state-machine/states/check-running.d.ts.map +1 -0
  400. package/dist/state-machine/states/completed.d.ts +12 -0
  401. package/dist/state-machine/states/completed.d.ts.map +1 -0
  402. package/dist/state-machine/states/error.d.ts +11 -0
  403. package/dist/state-machine/states/error.d.ts.map +1 -0
  404. package/dist/state-machine/states/init.d.ts +11 -0
  405. package/dist/state-machine/states/init.d.ts.map +1 -0
  406. package/dist/state-machine/states/level-dispatch.d.ts +17 -0
  407. package/dist/state-machine/states/level-dispatch.d.ts.map +1 -0
  408. package/dist/state-machine/states/plan-ready.d.ts +12 -0
  409. package/dist/state-machine/states/plan-ready.d.ts.map +1 -0
  410. package/dist/state-machine/states/routing.d.ts +52 -0
  411. package/dist/state-machine/states/routing.d.ts.map +1 -0
  412. package/dist/state-machine/states/wave-planning.d.ts +14 -0
  413. package/dist/state-machine/states/wave-planning.d.ts.map +1 -0
  414. package/dist/state-machine/workflow-projection.d.ts +47 -0
  415. package/dist/state-machine/workflow-projection.d.ts.map +1 -0
  416. package/dist/state-machine-execution-engine.d.ts +159 -0
  417. package/dist/state-machine-execution-engine.d.ts.map +1 -0
  418. package/dist/telemetry/opentelemetry.d.ts.map +1 -1
  419. package/dist/telemetry/state-capture.d.ts +5 -0
  420. package/dist/telemetry/state-capture.d.ts.map +1 -1
  421. package/dist/test-runner/assertions.d.ts +59 -0
  422. package/dist/test-runner/assertions.d.ts.map +1 -0
  423. package/dist/test-runner/core/environment.d.ts +8 -0
  424. package/dist/test-runner/core/environment.d.ts.map +1 -0
  425. package/dist/test-runner/core/fixture.d.ts +3 -0
  426. package/dist/test-runner/core/fixture.d.ts.map +1 -0
  427. package/dist/test-runner/core/flow-stage.d.ts +32 -0
  428. package/dist/test-runner/core/flow-stage.d.ts.map +1 -0
  429. package/dist/test-runner/core/mocks.d.ts +8 -0
  430. package/dist/test-runner/core/mocks.d.ts.map +1 -0
  431. package/dist/test-runner/core/test-execution-wrapper.d.ts +18 -0
  432. package/dist/test-runner/core/test-execution-wrapper.d.ts.map +1 -0
  433. package/dist/test-runner/evaluators.d.ts +45 -0
  434. package/dist/test-runner/evaluators.d.ts.map +1 -0
  435. package/dist/test-runner/fixture-loader.d.ts +30 -0
  436. package/dist/test-runner/fixture-loader.d.ts.map +1 -0
  437. package/dist/test-runner/index.d.ts +127 -0
  438. package/dist/test-runner/index.d.ts.map +1 -0
  439. package/dist/test-runner/recorders/github-recorder.d.ts +23 -0
  440. package/dist/test-runner/recorders/github-recorder.d.ts.map +1 -0
  441. package/dist/test-runner/recorders/global-recorder.d.ts +4 -0
  442. package/dist/test-runner/recorders/global-recorder.d.ts.map +1 -0
  443. package/dist/test-runner/recorders/slack-recorder.d.ts +17 -0
  444. package/dist/test-runner/recorders/slack-recorder.d.ts.map +1 -0
  445. package/dist/test-runner/utils/selectors.d.ts +2 -0
  446. package/dist/test-runner/utils/selectors.d.ts.map +1 -0
  447. package/dist/test-runner/validator.d.ts +8 -0
  448. package/dist/test-runner/validator.d.ts.map +1 -0
  449. package/dist/traces/run-2026-01-20T19-22-58-043Z.ndjson +138 -0
  450. package/dist/traces/run-2026-01-20T19-23-52-175Z.ndjson +1067 -0
  451. package/dist/types/bot.d.ts +109 -0
  452. package/dist/types/bot.d.ts.map +1 -0
  453. package/dist/types/cli.d.ts +8 -1
  454. package/dist/types/cli.d.ts.map +1 -1
  455. package/dist/types/config.d.ts +459 -9
  456. package/dist/types/config.d.ts.map +1 -1
  457. package/dist/types/engine.d.ts +177 -0
  458. package/dist/types/engine.d.ts.map +1 -0
  459. package/dist/types/execution.d.ts +73 -0
  460. package/dist/types/execution.d.ts.map +1 -0
  461. package/dist/types/git-checkout.d.ts +76 -0
  462. package/dist/types/git-checkout.d.ts.map +1 -0
  463. package/dist/types/github.d.ts +51 -0
  464. package/dist/types/github.d.ts.map +1 -0
  465. package/dist/types/workflow.d.ts +237 -0
  466. package/dist/types/workflow.d.ts.map +1 -0
  467. package/dist/utils/command-executor.d.ts +43 -0
  468. package/dist/utils/command-executor.d.ts.map +1 -0
  469. package/dist/utils/comment-metadata.d.ts +21 -0
  470. package/dist/utils/comment-metadata.d.ts.map +1 -0
  471. package/dist/utils/config-loader.d.ts.map +1 -1
  472. package/dist/utils/config-merger.d.ts.map +1 -1
  473. package/dist/utils/env-exposure.d.ts +3 -0
  474. package/dist/utils/env-exposure.d.ts.map +1 -0
  475. package/dist/utils/file-exclusion.d.ts.map +1 -1
  476. package/dist/utils/interactive-prompt.d.ts +1 -1
  477. package/dist/utils/interactive-prompt.d.ts.map +1 -1
  478. package/dist/utils/json-text-extractor.d.ts +17 -0
  479. package/dist/utils/json-text-extractor.d.ts.map +1 -0
  480. package/dist/utils/sandbox.d.ts +10 -0
  481. package/dist/utils/sandbox.d.ts.map +1 -1
  482. package/dist/utils/script-memory-ops.d.ts +21 -0
  483. package/dist/utils/script-memory-ops.d.ts.map +1 -0
  484. package/dist/utils/template-context.d.ts +8 -0
  485. package/dist/utils/template-context.d.ts.map +1 -0
  486. package/dist/utils/tracer-init.d.ts.map +1 -1
  487. package/dist/utils/workspace-manager.d.ts +118 -0
  488. package/dist/utils/workspace-manager.d.ts.map +1 -0
  489. package/dist/utils/worktree-cleanup.d.ts +33 -0
  490. package/dist/utils/worktree-cleanup.d.ts.map +1 -0
  491. package/dist/utils/worktree-manager.d.ts +153 -0
  492. package/dist/utils/worktree-manager.d.ts.map +1 -0
  493. package/dist/webhook-server.d.ts +3 -3
  494. package/dist/webhook-server.d.ts.map +1 -1
  495. package/dist/workflow-executor.d.ts +81 -0
  496. package/dist/workflow-executor.d.ts.map +1 -0
  497. package/dist/workflow-registry.d.ts +79 -0
  498. package/dist/workflow-registry.d.ts.map +1 -0
  499. package/package.json +12 -5
  500. package/dist/output/traces/run-2025-10-22T18-22-56-873Z.ndjson +0 -218
  501. package/dist/sdk/check-execution-engine-2YYKUUSH.mjs +0 -11
  502. package/dist/sdk/check-execution-engine-6QJXYYON.mjs +0 -11
  503. package/dist/sdk/check-execution-engine-PJZ4ZOKG.mjs +0 -11
  504. package/dist/sdk/chunk-33QVZ2D4.mjs +0 -316
  505. package/dist/sdk/chunk-33QVZ2D4.mjs.map +0 -1
  506. package/dist/sdk/chunk-B5QBV2QJ.mjs +0 -752
  507. package/dist/sdk/chunk-B5QBV2QJ.mjs.map +0 -1
  508. package/dist/sdk/chunk-BVFNRCHT.mjs +0 -14129
  509. package/dist/sdk/chunk-BVFNRCHT.mjs.map +0 -1
  510. package/dist/sdk/chunk-KWZW23FG.mjs +0 -14129
  511. package/dist/sdk/chunk-KWZW23FG.mjs.map +0 -1
  512. package/dist/sdk/chunk-O4RP4BRH.mjs +0 -14092
  513. package/dist/sdk/chunk-O4RP4BRH.mjs.map +0 -1
  514. package/dist/sdk/chunk-TUTOLSFV.mjs.map +0 -1
  515. package/dist/sdk/chunk-U5D2LY66.mjs +0 -245
  516. package/dist/sdk/chunk-U5D2LY66.mjs.map +0 -1
  517. package/dist/sdk/chunk-U7X54EMV.mjs +0 -331
  518. package/dist/sdk/chunk-U7X54EMV.mjs.map +0 -1
  519. package/dist/sdk/config-merger-TWUBWFC2.mjs +0 -8
  520. package/dist/sdk/mermaid-telemetry-SN6A2TKW.mjs +0 -61
  521. package/dist/sdk/mermaid-telemetry-SN6A2TKW.mjs.map +0 -1
  522. package/dist/sdk/mermaid-telemetry-YCTIG76M.mjs +0 -61
  523. package/dist/sdk/mermaid-telemetry-YCTIG76M.mjs.map +0 -1
  524. package/dist/traces/run-2025-10-22T18-22-56-873Z.ndjson +0 -218
  525. /package/dist/sdk/{check-execution-engine-2YYKUUSH.mjs.map → check-provider-registry-534KL5HT.mjs.map} +0 -0
  526. /package/dist/sdk/{check-execution-engine-6QJXYYON.mjs.map → command-executor-TYUV6HUS.mjs.map} +0 -0
  527. /package/dist/sdk/{check-execution-engine-PJZ4ZOKG.mjs.map → config-YNC2EOOT.mjs.map} +0 -0
  528. /package/dist/sdk/{config-merger-TWUBWFC2.mjs.map → config-merger-PX3WIT57.mjs.map} +0 -0
  529. /package/dist/sdk/{liquid-extensions-KVL4MKRH.mjs.map → failure-condition-evaluator-YGTF2GHG.mjs.map} +0 -0
  530. /package/dist/sdk/{tracer-init-WC75N5NW.mjs.map → liquid-extensions-PKWCKK7E.mjs.map} +0 -0
@@ -0,0 +1,473 @@
1
+ # ForEach Output: Validation, Dependent Propagation, and on_finish
2
+
3
+ This doc clarifies how `forEach` output is validated, how it affects dependent checks, and how to use the `on_finish` hook for aggregation and routing after all forEach iterations complete.
4
+
5
+ ## Valid and invalid outputs
6
+
7
+ - `transform_js` or provider output must resolve to a value. If it is `undefined`, the engine emits an error:
8
+ - Issue: `forEach/undefined_output`
9
+ - Effect: direct dependents are skipped (`dependency_failed`).
10
+ - If the value is an array, the engine iterates items.
11
+ - If the value is a string, the engine tries to JSON.parse it; if it parses to an array, that array is used; otherwise it treats the string as a single item.
12
+ - If the value is `null`, it is normalized to an empty array (0 iterations).
13
+
14
+ ## Empty arrays vs undefined
15
+
16
+ - `[]` (empty array): valid — the check runs zero iterations. Dependents that rely on items are effectively skipped (no provider execution), and you’ll see a log like:
17
+
18
+ ```
19
+ forEach: no items from "fetch-tickets", skipping check...
20
+ ```
21
+
22
+ - `undefined`: invalid — treated as a configuration/transform error. The engine emits a `forEach/undefined_output` issue and skips direct dependents.
23
+
24
+ ## Example
25
+
26
+ ```yaml
27
+ steps:
28
+ fetch-tickets:
29
+ type: command
30
+ exec: echo '{"tickets": []}'
31
+ transform_js: JSON.parse(output).tickets
32
+ forEach: true
33
+
34
+ analyze-ticket:
35
+ type: command
36
+ depends_on: [fetch-tickets]
37
+ exec: echo "TICKET: {{ outputs['fetch-tickets'].key }}"
38
+ ```
39
+
40
+ - If `tickets` is `[]`, `analyze-ticket` is effectively skipped (no per‑item execution).
41
+ - If `transform_js` returns `undefined`, the engine raises `forEach/undefined_output` and `analyze-ticket` is skipped due to a failed dependency.
42
+
43
+ ## Output Access and History with forEach
44
+
45
+ When a check has `forEach: true`, three accessors are available:
46
+ - `outputs['check-name']` — nearest value in scope (inside an iteration, this is the current item).
47
+ - `outputs_raw['check-name']` — aggregate/parent value (the full array produced by the forEach parent).
48
+ - `outputs.history['check-name']` — all committed values up to the current snapshot (alias: `outputs_history['check-name']`).
49
+
50
+ ```yaml
51
+ steps:
52
+ process-items:
53
+ type: script
54
+ depends_on: [fetch-tickets]
55
+ forEach: true
56
+ content: |
57
+ const curr = outputs['fetch-tickets'];
58
+ return { itemId: curr.key, processed: true };
59
+
60
+ summarize:
61
+ type: script
62
+ depends_on: [process-items]
63
+ content: |
64
+ // Access all forEach iteration results
65
+ const allProcessed = outputs.history['process-items']; # or outputs_history['process-items']
66
+ return { totalProcessed: allProcessed.length };
67
+ ```
68
+
69
+ Precedence rules (summary):
70
+ - `outputs['x']` resolves to the nearest item if inside a per-item scope of `x`; otherwise to an ancestor value; otherwise to the latest committed.
71
+ - `outputs_raw['x']` resolves to the shallowest/aggregate scope of `x` (e.g., the full array for a forEach parent).
72
+ - `outputs.history['x']` returns all committed values for `x` in this session up to the snapshot.
73
+
74
+ Routing JS also gets `outputs_raw` with the same semantics, so you can branch on the aggregate even when you’re inside a per-item iteration.
75
+
76
+ See [Output History](./output-history.md) for more details on tracking outputs across iterations.
77
+
78
+ ## The on_finish Hook: Lifecycle Extension
79
+
80
+ The `on_finish` hook is a special routing action that extends the forEach lifecycle. It triggers **once** after **all** dependent checks complete **all** their iterations, providing a single point for aggregation and routing decisions.
81
+
82
+ ### Complete forEach Lifecycle
83
+
84
+ ```
85
+ 1. forEach Check Executes
86
+ └─> Outputs array: [item1, item2, item3]
87
+
88
+ 2. Dependent Checks Execute (N iterations)
89
+ ├─> dependent-check runs for item1
90
+ ├─> dependent-check runs for item2
91
+ └─> dependent-check runs for item3
92
+
93
+ 3. on_finish Hook Triggers (on the forEach check)
94
+ ├─> on_finish.run executes (optional aggregation checks)
95
+ ├─> on_finish.run_js evaluates (optional dynamic checks)
96
+ ├─> on_finish.goto_js evaluates (optional routing decision)
97
+ └─> If goto returns a check name, jump to that ancestor
98
+
99
+ 4. Downstream Checks Execute
100
+ └─> Checks that don't depend on the forEach check continue
101
+ ```
102
+
103
+ ### When on_finish Triggers
104
+
105
+ - **Only** on checks with `forEach: true`
106
+ - **After** ALL dependent checks complete ALL iterations
107
+ - **Does not** trigger if forEach array is empty (`[]`)
108
+ - **Does not** trigger if output is `undefined` (error state)
109
+ - **Always** triggers after successful forEach propagation
110
+
111
+ ### Configuration
112
+
113
+ ```yaml
114
+ checks:
115
+ extract-facts:
116
+ type: ai
117
+ forEach: true
118
+ prompt: "Extract facts from {{ outputs.response }}"
119
+ transform_js: JSON.parse(output).facts
120
+
121
+ # on_finish runs after all validate-fact iterations complete
122
+ on_finish:
123
+ # Optional: Run aggregation checks
124
+ run: [aggregate-validations]
125
+
126
+ # Optional: Make routing decision
127
+ goto_js: |
128
+ const allValid = memory.get('all_facts_valid', 'validation');
129
+ const attempt = memory.get('fact_validation_attempt', 'validation') || 0;
130
+
131
+ if (allValid) {
132
+ return null; // Continue to downstream checks
133
+ }
134
+
135
+ if (attempt >= 1) {
136
+ return null; // Max attempts, give up
137
+ }
138
+
139
+ memory.increment('fact_validation_attempt', 1, 'validation');
140
+ return 'generate-response'; // Jump back to ancestor
141
+
142
+ # Optional: Override event for goto target
143
+ goto_event: issue_opened
144
+
145
+ validate-fact:
146
+ type: ai
147
+ depends_on: [extract-facts]
148
+ # Runs N times (once per fact)
149
+
150
+ aggregate-validations:
151
+ type: script
152
+ fanout: reduce # ensure single aggregation run after forEach
153
+ content: |
154
+ // Access all validation results
155
+ const validations = outputs.history['validate-fact'];
156
+ const allValid = validations.every(v => v.is_valid);
157
+ memory.set('all_facts_valid', allValid, 'validation');
158
+ return { total: validations.length, valid: allValid };
159
+ ```
160
+
161
+ ### Context Available in on_finish
162
+
163
+ ```javascript
164
+ {
165
+ step: {
166
+ id: 'extract-facts',
167
+ tags: [...],
168
+ group: '...'
169
+ },
170
+ attempt: 1, // Attempt number for this check
171
+ loop: 2, // Loop number in routing
172
+ outputs: {
173
+ 'extract-facts': [...], // The forEach array
174
+ 'validate-fact': [...], // Latest dependent results
175
+ },
176
+ outputs.history: {
177
+ 'extract-facts': [[...], ...], // Historical forEach outputs
178
+ 'validate-fact': [[...], ...], // ALL iteration results
179
+ },
180
+ forEach: {
181
+ total: 3, // Number of items processed
182
+ successful: 3, // Successful iterations
183
+ failed: 0, // Failed iterations
184
+ items: [...] // The forEach items array
185
+ },
186
+ memory, // Memory access functions
187
+ pr, // PR metadata
188
+ files, // Changed files
189
+ env // Environment variables
190
+ }
191
+ ```
192
+
193
+ ### Flow Diagram with on_finish
194
+
195
+ ```
196
+ ┌─────────────────────┐
197
+ │ forEach Check │
198
+ │ outputs: [1,2,3] │
199
+ └──────────┬──────────┘
200
+
201
+ ├──────────────────────────────┐
202
+ │ │
203
+ ▼ ▼
204
+ ┌──────────────┐ ┌──────────────┐
205
+ │ Dependent A │ │ Dependent B │
206
+ │ (3 times) │ │ (3 times) │
207
+ └──────┬───────┘ └──────┬───────┘
208
+ │ │
209
+ └───────────┬───────────────┘
210
+
211
+
212
+ ┌─────────────────────┐
213
+ │ on_finish hook │
214
+ │ ┌─────────────┐ │
215
+ │ │ run: [] │ │
216
+ │ ├─────────────┤ │
217
+ │ │ goto_js │ │
218
+ │ └─────────────┘ │
219
+ └──────────┬──────────┘
220
+
221
+ ┌─────────────┴──────────────┐
222
+ │ │
223
+ ▼ ▼
224
+ goto target? Downstream
225
+ (ancestor) Checks
226
+ ```
227
+
228
+ ### Example: Validation with Retry
229
+
230
+ A complete example showing validation, aggregation, and retry:
231
+
232
+ ```yaml
233
+ checks:
234
+ # Step 1: Generate initial response
235
+ generate-response:
236
+ type: ai
237
+ prompt: "Generate response for: {{ event.issue.body }}"
238
+
239
+ # Step 2: Extract facts (forEach)
240
+ extract-facts:
241
+ type: ai
242
+ depends_on: [generate-response]
243
+ forEach: true
244
+ prompt: |
245
+ Extract verifiable facts from: {{ outputs['generate-response'] }}
246
+ Return JSON: [{"claim": "...", "category": "..."}]
247
+ transform_js: JSON.parse(output)
248
+
249
+ # Step 5: Aggregate and route
250
+ on_finish:
251
+ run: [aggregate-validations]
252
+ goto_js: |
253
+ const allValid = memory.get('all_valid', 'fact-validation');
254
+ const attempt = memory.get('attempt', 'fact-validation') || 0;
255
+
256
+ log('Validation complete:', {
257
+ allValid,
258
+ attempt,
259
+ forEach: forEach.total + ' facts checked'
260
+ });
261
+
262
+ if (allValid) {
263
+ log('All valid, proceeding to post');
264
+ return null;
265
+ }
266
+
267
+ if (attempt >= 1) {
268
+ log('Max attempts reached');
269
+ return null;
270
+ }
271
+
272
+ log('Retrying with validation context');
273
+ memory.increment('attempt', 1, 'fact-validation');
274
+ return 'generate-response';
275
+
276
+ # Step 3: Validate each fact (runs N times)
277
+ validate-fact:
278
+ type: ai
279
+ depends_on: [extract-facts]
280
+ prompt: |
281
+ Verify this fact using code search:
282
+ Claim: {{ outputs['extract-facts'].claim }}
283
+ Category: {{ outputs['extract-facts'].category }}
284
+
285
+ Return JSON: {"is_valid": true/false, "evidence": "..."}
286
+ transform_js: JSON.parse(output)
287
+
288
+ # Step 4: Aggregate all validation results
289
+ aggregate-validations:
290
+ type: script
291
+ content: |
292
+ // Get ALL validation results from forEach iterations
293
+ const validations = outputs.history['validate-fact'];
294
+
295
+ log('Aggregating', validations.length, 'validations');
296
+
297
+ const invalid = validations.filter(v => !v.is_valid);
298
+ const allValid = invalid.length === 0;
299
+
300
+ // Store for goto_js and downstream checks
301
+ memory.set('all_valid', allValid, 'fact-validation');
302
+ memory.set('invalid_count', invalid.length, 'fact-validation');
303
+
304
+ // Store issues for retry context
305
+ if (!allValid) {
306
+ memory.set('validation_issues', invalid, 'fact-validation');
307
+ }
308
+
309
+ return {
310
+ total: validations.length,
311
+ valid: validations.length - invalid.length,
312
+ invalid: invalid.length,
313
+ all_valid: allValid
314
+ };
315
+
316
+ # Step 6: Post response (only if valid)
317
+ post-response:
318
+ type: github
319
+ depends_on: [extract-facts]
320
+ if: "memory.get('all_valid', 'fact-validation') === true"
321
+ op: comment.create
322
+ value: "{{ outputs['generate-response'] }}"
323
+ ```
324
+
325
+ **Flow:**
326
+ 1. `generate-response` runs → outputs AI response
327
+ 2. `extract-facts` runs → outputs `[fact1, fact2, fact3]`
328
+ 3. `validate-fact` runs 3 times (once per fact)
329
+ 4. **on_finish triggers:**
330
+ - `aggregate-validations` runs → stores results in memory
331
+ - `goto_js` evaluates → returns `'generate-response'` or `null`
332
+ 5. If goto returned a check name:
333
+ - Jump to `generate-response` (with incremented attempt counter)
334
+ - Re-run the entire flow with validation context
335
+ 6. If goto returned `null`:
336
+ - Continue to `post-response` (if validation passed)
337
+
338
+ ### Multiple Dependents Pattern
339
+
340
+ The power of `on_finish` is aggregating across **multiple** dependent checks:
341
+
342
+ ```yaml
343
+ checks:
344
+ extract-claims:
345
+ type: ai
346
+ forEach: true
347
+ on_finish:
348
+ run: [aggregate-all]
349
+ goto_js: |
350
+ const securityOk = memory.get('security_ok', 'validation');
351
+ const techOk = memory.get('tech_ok', 'validation');
352
+ return (securityOk && techOk) ? null : 'retry';
353
+
354
+ # Multiple dependents, all run N times
355
+ validate-security:
356
+ depends_on: [extract-claims]
357
+
358
+ validate-technical:
359
+ depends_on: [extract-claims]
360
+
361
+ validate-style:
362
+ depends_on: [extract-claims]
363
+
364
+ aggregate-all:
365
+ type: script
366
+ fanout: reduce
367
+ content: |
368
+ // Access ALL results from ALL dependent checks
369
+ const security = outputs.history['validate-security'];
370
+ const technical = outputs.history['validate-technical'];
371
+ const style = outputs.history['validate-style'];
372
+
373
+ memory.set('security_ok', security.every(r => r.valid), 'validation');
374
+ memory.set('tech_ok', technical.every(r => r.valid), 'validation');
375
+ memory.set('style_ok', style.every(r => r.valid), 'validation');
376
+
377
+ return { aggregated: true };
378
+ ```
379
+
380
+ This is the **only way** to aggregate across multiple dependent checks after forEach completes.
381
+
382
+ ### Error Handling in on_finish
383
+
384
+ - If `on_finish.run` checks fail, the forEach check is marked as failed
385
+ - If `goto_js` throws an error, the engine falls back to static `goto` (if present)
386
+ - If no fallback exists, the error is logged and execution continues
387
+ - Loop safety: `on_finish.goto` counts toward `routing.max_loops`
388
+
389
+ ### Best Practices for on_finish
390
+
391
+ 1. **Always Aggregate First**: Use `on_finish.run` to aggregate before `goto_js` runs
392
+ 2. **Use outputs.history**: Access all iteration results with `outputs.history['check-name']`
393
+ 3. **Store in Memory**: Pass aggregated state to `goto_js` and downstream checks via memory
394
+ 4. **Limit Retries**: Track attempt counts in memory to prevent infinite loops
395
+ 5. **Handle Empty Arrays**: Check `forEach.total` or array length before processing
396
+ 6. **Log Decisions**: Use `log()` in JavaScript to debug routing decisions
397
+ 7. **Check Multiple Dependents**: Perfect for scenarios with multiple dependent checks
398
+
399
+ ### Common Pitfalls
400
+
401
+ ❌ **Don't** use `on_finish` on non-forEach checks:
402
+ ```yaml
403
+ regular-check:
404
+ type: command
405
+ on_finish: # ❌ ERROR: on_finish requires forEach: true
406
+ run: [something]
407
+ ```
408
+
409
+ ❌ **Don't** forget to return from `goto_js`:
410
+ ```javascript
411
+ goto_js: |
412
+ const shouldRetry = memory.get('should_retry');
413
+ 'retry-check'; // ❌ Missing return statement
414
+ ```
415
+
416
+ ✅ **Do** return explicitly:
417
+ ```javascript
418
+ goto_js: |
419
+ const shouldRetry = memory.get('should_retry');
420
+ return shouldRetry ? 'retry-check' : null; // ✅ Explicit return
421
+ ```
422
+
423
+ ❌ **Don't** access `outputs['check']` for iteration results:
424
+ ```javascript
425
+ // ❌ Only gives latest result
426
+ const results = outputs['validate-fact'];
427
+ ```
428
+
429
+ ✅ **Do** use `outputs.history` for all iterations:
430
+ ```javascript
431
+ // ✅ All iteration results
432
+ const results = outputs.history['validate-fact'];
433
+ ```
434
+
435
+ ## Tips
436
+
437
+ - Always `return` from `transform_js`. Missing `return` is the most common cause of `undefined`.
438
+ - Prefer returning arrays directly from `transform_js` (avoid stringifying) to keep types clear and avoid parsing surprises.
439
+ - Use `outputs.history` to access all forEach iteration results in dependent checks and `on_finish` hooks.
440
+ - Use `on_finish` for aggregation after all forEach iterations complete.
441
+ - Store aggregated state in memory for use in `goto_js` and downstream checks.
442
+ - Track attempt counters in memory to prevent infinite retry loops.
443
+
444
+ ## See Also
445
+
446
+ - [Failure Routing](./failure-routing.md) - Complete `on_finish` reference with examples
447
+ - [Dependencies](./dependencies.md) - `on_finish` with forEach propagation patterns
448
+ - [Output History](./output-history.md) - Accessing historical outputs across iterations
449
+ - [examples/fact-validator.yaml](../examples/fact-validator.yaml) - Complete working example
450
+ ## Fan-out Control for Routing (Phase 5)
451
+
452
+ When routing from a forEach context, you can opt into per‑item runs without writing manual loops:
453
+
454
+ - Add `fanout: map` to the target check to schedule it once per item.
455
+ - Add `fanout: reduce` (or `reduce: true`) to run once at the parent scope (default).
456
+
457
+ This works with `on_success.run/goto`, `on_fail.run/goto`, and `on_finish.run/goto`.
458
+
459
+ Example:
460
+ ```yaml
461
+ checks:
462
+ files:
463
+ type: command
464
+ exec: git ls-files '*.ts'
465
+ forEach: true
466
+ on_success:
467
+ run: [lint-file]
468
+
469
+ lint-file:
470
+ type: command
471
+ fanout: map
472
+ exec: eslint {{ outputs['files'] }}
473
+ ```
@@ -0,0 +1,89 @@
1
+ # Native GitHub Provider
2
+
3
+ The `github` provider performs safe, native GitHub operations via Octokit — no shelling out to `gh`.
4
+
5
+ - Supported ops: `labels.add`, `labels.remove`, `comment.create`.
6
+ - Works on Pull Requests and Issues (uses the current PR/issue number from the event context).
7
+ - Returns provider issues on failures instead of crashing the run.
8
+
9
+ ## Requirements
10
+
11
+ - `GITHUB_TOKEN` (or the Action input `github-token`) must be present.
12
+ - `GITHUB_REPOSITORY` is auto‑set in Actions.
13
+
14
+ ## Configuration
15
+
16
+ ```yaml
17
+ steps:
18
+ apply-overview-labels:
19
+ type: github
20
+ group: github
21
+ tags: [github]
22
+ depends_on: [overview]
23
+ on: [pr_opened, pr_updated]
24
+ op: labels.add
25
+ values:
26
+ - "{{ outputs.overview.tags.label | default: '' | safe_label }}"
27
+ - "{{ outputs.overview.tags['review-effort'] | default: '' | prepend: 'review/effort:' | safe_label }}"
28
+ ```
29
+
30
+ Notes:
31
+ - Empty strings are ignored automatically; no `value_js` needed to filter them out.
32
+
33
+ ### Issues (Errors) Emitted
34
+
35
+ When the provider cannot perform an operation, it returns a synthetic issue in the check’s output:
36
+
37
+ - `github/missing_token` — no token available
38
+ - `github/missing_context` — missing owner/repo/PR number
39
+ - `github/unsupported_op` — unknown `op`
40
+ - `github/value_js_error` — exception thrown while evaluating `value_js`
41
+ - `github/op_failed` — Octokit call failed (includes error message)
42
+
43
+ These issues are visible in tables/markdown output and will not abort the whole workflow; use `fail_if` to control behavior.
44
+
45
+ ## Labels: Sanitization
46
+
47
+ To prevent injection and ensure GitHub‑compatible labels, use Liquid filters:
48
+
49
+ - `safe_label` — keeps only `[A-Za-z0-9:/\- ]` (alphanumerics, colon, slash, hyphen, and space), collapses repeated `/`, and trims whitespace.
50
+ - `safe_label_list` — applies `safe_label` to arrays and removes empty values.
51
+
52
+ Examples:
53
+ ```yaml
54
+ values:
55
+ - "{{ outputs['issue-assistant'].tags.label | safe_label }}"
56
+ - "{{ outputs.overview.tags['review-effort'] | prepend: 'review/effort:' | safe_label }}"
57
+ ```
58
+
59
+ > Important: Do not build shell commands from labels. The `github` provider calls the API directly.
60
+
61
+ ## Creating Comments
62
+
63
+ ```yaml
64
+ steps:
65
+ post-note:
66
+ type: github
67
+ op: comment.create
68
+ values:
69
+ - "Automated note for PR #{{ pr.number }}"
70
+ - "\nDetails: {{ outputs.security.text | default: '' | unescape_newlines }}"
71
+ ```
72
+
73
+ ## Removing Labels
74
+
75
+ ```yaml
76
+ steps:
77
+ cleanup-labels:
78
+ type: github
79
+ op: labels.remove
80
+ values:
81
+ - legacy/triage
82
+ - stale
83
+ ```
84
+
85
+ ## Tips
86
+
87
+ - Combine Liquid and `value_js` to build dynamic, multi‑label operations safely.
88
+ - Use `tags: [github]` to run these checks only in Actions (paired with `--tags github`).
89
+ - Pair with `if:` conditions to gate on prior outputs, e.g., apply labels only when `outputs.overview.tags.label` exists.
@@ -0,0 +1,113 @@
1
+ # Visor Engine Plan: Use `goto` for Looping on Failures
2
+
3
+ This document captures the plan to simplify looping by using `goto` in `on_fail` and letting the engine re‑run the dependent chain deterministically.
4
+
5
+ ## Background
6
+
7
+ Today, builder YAML uses `on_fail.run: [agent-refine, agent-write, config-lint, tests-validate, agent-verify-tests, …]` to bounce back through the pipeline. This is verbose and couples control‑flow to YAML.
8
+
9
+ Engine behavior:
10
+ - `on_success.goto` performs a forward‑run: it executes the `goto` target and all its dependents in topological order.
11
+ - `on_fail.goto` is currently limited to ancestor targets and does not forward‑run dependents.
12
+
13
+ ## Goal
14
+
15
+ Allow clean, minimal YAML that uses only `goto` for looping:
16
+ - Validators: `on_fail: goto: agent-refine` (or directly `goto: agent-write`).
17
+ - Refine: `on_success: goto: agent-write`.
18
+
19
+ The engine should handle re‑running the necessary chain; YAML should not list the entire sequence.
20
+
21
+ ## Proposed Engine Changes
22
+
23
+ 1) Unify `goto` semantics across origins
24
+ - Make `goto` perform the same forward‑run whether invoked from `on_success`, `on_fail`, or `on_finish`.
25
+ - Factor shared code into a helper (e.g., `scheduleForwardRun(target, opts)`), currently implemented only inside the `on_success.goto` branch.
26
+
27
+ 2) Relax ancestor‑only restriction for `on_fail.goto`
28
+ - Allow `goto` to any step in the DAG, not only ancestors.
29
+ - Keep safety guards (below) to prevent runaway loops.
30
+
31
+ 3) Optional: Add anchors
32
+ - Introduce `anchor: true` (or `loop_anchor: true`) on steps like `agent-write`.
33
+ - If a validator has `on_fail` without explicit `goto`, engine can jump to the nearest anchor.
34
+
35
+ 4) Loop safety and predictability
36
+ - Keep `routing.max_loops` budget (already implemented).
37
+ - Respect `one_shot` tag: skip re‑running steps with `tags: [one_shot]` that already executed in this run.
38
+ - Maintain per‑run statistics to avoid duplicate scheduling within a wave.
39
+
40
+ 5) Forward‑run details
41
+ - From the target (e.g., `agent-write`), compute the dependent subgraph (topological order) honoring `depends_on` and event filters.
42
+ - Preserve current event by default; honor `goto_event` only when explicitly provided.
43
+
44
+ ## YAML Patterns After the Change
45
+
46
+ Pattern A (pure goto):
47
+ - Validators (`config-lint`, `tests-validate`, `agent-verify-tests`):
48
+ ```yaml
49
+ on_fail:
50
+ goto: agent-refine
51
+ ```
52
+ - Refine:
53
+ ```yaml
54
+ on_success:
55
+ goto: agent-write
56
+ ```
57
+
58
+ Pattern B (single hop to anchor):
59
+ - Validators:
60
+ ```yaml
61
+ on_fail:
62
+ goto: agent-write
63
+ ```
64
+
65
+ ## Migration Plan
66
+
67
+ 1) Engine implementation
68
+ - Unify forward‑run for `goto` in `on_fail` and `on_finish`.
69
+ - Remove ancestor‑only restriction or gate it behind a feature flag (e.g., `VISOR_GOTO_GLOBAL=true`).
70
+ - Extract forward‑run into a shared helper.
71
+
72
+ 2) Builder YAML simplification
73
+ - Replace `on_fail.run: [ …full list… ]` with `on_fail: goto: agent-refine`.
74
+ - Keep `agent-refine on_success: goto: agent-write`.
75
+
76
+ 3) Tests (exact counts only)
77
+ - Single‑invocation multi‑refine (3 cycles):
78
+ - `refine = 3`, `write/lint/validate = 4`, `verify-tests = 3`, `code-review/cleanup/finish = 1`.
79
+ - Flow tests (staged multi‑refine) remain for readability.
80
+ - Edge cases: loop budget exceeded, `one_shot` steps, event override.
81
+
82
+ ## Code Pointers
83
+
84
+ File: `src/check-execution-engine.ts`
85
+ - `executeWithRouting` — handles `on_fail.run/goto` and `on_success.run/goto`:
86
+ - Unify forward‑run behavior for `goto` across origins.
87
+ - Current forward‑run logic lives in the `on_success.goto` branch (search for comments near topological ordering and `forwardSet`).
88
+ - `runNamedCheck` — respects `if` conditions and records stats; ensure forward‑run uses consistent overlays/results.
89
+ - Guards: `routing.max_loops`, `oncePerRun`/`one_shot` behavior, execution statistics.
90
+
91
+ Suggested refactor:
92
+ - Introduce `scheduleForwardRun(target, scope, opts)` used by all `goto` sites.
93
+ - Extract subgraph building + topo sort into a helper for reuse.
94
+
95
+ ## Telemetry / Debug
96
+ - Add concise debug logs for `goto` forward‑run across all origins: target, number of dependents, topological order.
97
+ - Keep existing OTEL and NDJSON traces.
98
+
99
+ ## Rollout
100
+ - Implemented without a feature flag. Old configs are not broken: `goto` to
101
+ ancestors preserves the previous “re-run ancestor only” behavior. New behavior
102
+ simply allows `goto` to any step and forward‑runs its dependents when routing
103
+ to a non‑ancestor.
104
+ - Builder YAML switched to pure `goto` in validators.
105
+
106
+ ## Open Questions
107
+ - Should `goto` always forward‑run, or only when target is an anchor? (Leaning: always forward‑run for clarity.)
108
+ - Should we auto‑select an anchor when `goto` target is omitted? (Future convenience.)
109
+
110
+ ## Acceptance Criteria
111
+ - Single‑run multi‑refine test passes with exact counts.
112
+ - Flow multi‑refine tests pass.
113
+ - No regression in existing suites; loop budget respected.