@probelabs/visor 0.1.124 → 0.1.126

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 (195) hide show
  1. package/dist/config.d.ts.map +1 -1
  2. package/dist/docs/DEPLOYMENT.md +117 -11
  3. package/dist/docs/GITHUB_CHECKS.md +18 -4
  4. package/dist/docs/NPM_USAGE.md +112 -39
  5. package/dist/docs/action-reference.md +63 -9
  6. package/dist/docs/advanced-ai.md +58 -51
  7. package/dist/docs/ai-configuration.md +99 -11
  8. package/dist/docs/ai-custom-tools-usage.md +70 -33
  9. package/dist/docs/ai-custom-tools.md +50 -27
  10. package/dist/docs/architecture.md +1232 -0
  11. package/dist/docs/bot-transports-rfc.md +13 -3
  12. package/dist/docs/ci-cli-mode.md +116 -8
  13. package/dist/docs/claude-code.md +111 -41
  14. package/dist/docs/command-provider.md +37 -15
  15. package/dist/docs/commands.md +252 -6
  16. package/dist/docs/configuration.md +138 -4
  17. package/dist/docs/contributing.md +737 -0
  18. package/dist/docs/custom-tools.md +39 -8
  19. package/dist/docs/dashboards/README.md +33 -19
  20. package/dist/docs/debug-visualizer-progress.md +14 -13
  21. package/dist/docs/debug-visualizer-rfc.md +14 -13
  22. package/dist/docs/debug-visualizer.md +30 -5
  23. package/dist/docs/debugging.md +73 -8
  24. package/dist/docs/default-output-schema.md +24 -20
  25. package/dist/docs/dependencies.md +75 -21
  26. package/dist/docs/dev-playbook.md +85 -9
  27. package/dist/docs/engine-pause-resume-rfc.md +11 -11
  28. package/dist/docs/engine-state-machine-plan.md +10 -3
  29. package/dist/docs/event-driven-github-integration-rfc.md +20 -11
  30. package/dist/docs/event-triggers.md +95 -6
  31. package/dist/docs/execution-statistics-rfc.md +16 -4
  32. package/dist/docs/fact-validator-gap-analysis.md +12 -1
  33. package/dist/docs/fact-validator-implementation-plan.md +19 -11
  34. package/dist/docs/fail-if.md +116 -11
  35. package/dist/docs/failure-conditions-implementation.md +40 -6
  36. package/dist/docs/failure-conditions-schema.md +243 -87
  37. package/dist/docs/failure-routing-rfc.md +43 -18
  38. package/dist/docs/failure-routing.md +80 -23
  39. package/dist/docs/faq.md +836 -0
  40. package/dist/docs/foreach-dependency-propagation.md +32 -15
  41. package/dist/docs/github-ops.md +6 -5
  42. package/dist/docs/glossary.md +322 -0
  43. package/dist/docs/goto-forward-run-plan.md +23 -10
  44. package/dist/docs/guides/criticality-modes.md +15 -13
  45. package/dist/docs/guides/fault-management-and-contracts.md +8 -5
  46. package/dist/docs/guides/workflow-style-guide.md +17 -8
  47. package/dist/docs/http.md +102 -3
  48. package/dist/docs/human-input-provider.md +20 -36
  49. package/dist/docs/index.md +206 -0
  50. package/dist/docs/lifecycle-hooks.md +322 -2
  51. package/dist/docs/limits.md +20 -5
  52. package/dist/docs/liquid-templates.md +86 -14
  53. package/dist/docs/loop-routing-refactor.md +4 -2
  54. package/dist/docs/mcp-provider.md +53 -19
  55. package/dist/docs/mcp.md +27 -1
  56. package/dist/docs/memory.md +7 -2
  57. package/dist/docs/migration.md +596 -0
  58. package/dist/docs/observability.md +227 -6
  59. package/dist/docs/output-formats.md +388 -9
  60. package/dist/docs/output-history.md +36 -6
  61. package/dist/docs/performance.md +510 -4
  62. package/dist/docs/pluggable.md +95 -4
  63. package/dist/docs/proposals/snapshot-scope-execution.md +6 -5
  64. package/dist/docs/providers/git-checkout.md +16 -14
  65. package/dist/docs/providers/noop.md +696 -0
  66. package/dist/docs/recipes.md +8 -9
  67. package/dist/docs/rfc/git-checkout-step.md +3 -1
  68. package/dist/docs/rfc/on_init-hook.md +18 -5
  69. package/dist/docs/rfc/workspace-isolation.md +16 -0
  70. package/dist/docs/roadmap/criticality-implementation-tasks.md +27 -27
  71. package/dist/docs/router-patterns.md +155 -43
  72. package/dist/docs/schema-templates.md +51 -15
  73. package/dist/docs/script.md +162 -13
  74. package/dist/docs/sdk.md +46 -12
  75. package/dist/docs/security.md +464 -5
  76. package/dist/docs/slack-integration.md +481 -0
  77. package/dist/docs/tag-filtering.md +60 -20
  78. package/dist/docs/telemetry-setup.md +157 -46
  79. package/dist/docs/test-framework-rfc.md +37 -36
  80. package/dist/docs/testing/assertions.md +92 -4
  81. package/dist/docs/testing/ci.md +56 -7
  82. package/dist/docs/testing/cli.md +57 -15
  83. package/dist/docs/testing/cookbook.md +53 -20
  84. package/dist/docs/testing/dsl-reference.md +110 -9
  85. package/dist/docs/testing/fixtures-and-mocks.md +28 -3
  86. package/dist/docs/testing/flows.md +59 -4
  87. package/dist/docs/testing/getting-started.md +14 -13
  88. package/dist/docs/testing/troubleshooting.md +39 -2
  89. package/dist/docs/timeouts.md +174 -18
  90. package/dist/docs/troubleshooting.md +176 -6
  91. package/dist/docs/workflow-creation-guide.md +101 -3
  92. package/dist/docs/workflows.md +138 -41
  93. package/dist/examples/README.md +169 -4
  94. package/dist/examples/ai-custom-tools-simple.yaml +2 -3
  95. package/dist/examples/cron-webhook-config.yaml +15 -0
  96. package/dist/examples/forEach-example.yaml +6 -0
  97. package/dist/examples/git-checkout-basic.yaml +4 -0
  98. package/dist/examples/git-checkout-compare.yaml +6 -0
  99. package/dist/examples/git-checkout-cross-repo.yaml +7 -0
  100. package/dist/examples/http-integration-config.yaml +30 -0
  101. package/dist/examples/https-server-config.yaml +15 -0
  102. package/dist/examples/mcp-provider-example.yaml +10 -10
  103. package/dist/examples/transform-example.yaml +3 -0
  104. package/dist/examples/webhook-pipeline-config.yaml +18 -0
  105. package/dist/examples/workflows/workflow-composition-example.yaml +4 -0
  106. package/dist/frontends/slack-frontend.d.ts +2 -0
  107. package/dist/frontends/slack-frontend.d.ts.map +1 -1
  108. package/dist/generated/config-schema.d.ts +11 -7
  109. package/dist/generated/config-schema.d.ts.map +1 -1
  110. package/dist/generated/config-schema.json +11 -7
  111. package/dist/index.js +3127 -974
  112. package/dist/output/traces/{run-2026-01-28T16-15-24-569Z.ndjson → run-2026-01-31T16-37-22-321Z.ndjson} +84 -84
  113. package/dist/output/traces/{run-2026-01-28T16-16-09-757Z.ndjson → run-2026-01-31T16-38-06-031Z.ndjson} +1013 -1013
  114. package/dist/providers/ai-check-provider.d.ts +9 -2
  115. package/dist/providers/ai-check-provider.d.ts.map +1 -1
  116. package/dist/providers/command-check-provider.d.ts.map +1 -1
  117. package/dist/providers/mcp-custom-sse-server.d.ts +17 -1
  118. package/dist/providers/mcp-custom-sse-server.d.ts.map +1 -1
  119. package/dist/providers/workflow-check-provider.d.ts.map +1 -1
  120. package/dist/providers/workflow-tool-executor.d.ts +68 -0
  121. package/dist/providers/workflow-tool-executor.d.ts.map +1 -0
  122. package/dist/sdk/{check-provider-registry-AQ3JETBG.mjs → check-provider-registry-3KI5RKXT.mjs} +6 -5
  123. package/dist/sdk/check-provider-registry-IYILYY35.mjs +28 -0
  124. package/dist/sdk/chunk-2CPMMNIX.mjs +1459 -0
  125. package/dist/sdk/chunk-2CPMMNIX.mjs.map +1 -0
  126. package/dist/sdk/chunk-5LI6T4O3.mjs +3600 -0
  127. package/dist/sdk/chunk-5LI6T4O3.mjs.map +1 -0
  128. package/dist/sdk/{chunk-YLQ4UN62.mjs → chunk-A4PGHURG.mjs} +6838 -6257
  129. package/dist/sdk/chunk-A4PGHURG.mjs.map +1 -0
  130. package/dist/sdk/chunk-EXFGO4FX.mjs +147 -0
  131. package/dist/sdk/chunk-EXFGO4FX.mjs.map +1 -0
  132. package/dist/sdk/chunk-PJ7K5UFC.mjs +17732 -0
  133. package/dist/sdk/chunk-PJ7K5UFC.mjs.map +1 -0
  134. package/dist/sdk/{chunk-BHZ4CKUS.mjs → chunk-PXFIALUH.mjs} +77 -8
  135. package/dist/sdk/chunk-PXFIALUH.mjs.map +1 -0
  136. package/dist/sdk/{chunk-PVITVJ6J.mjs → chunk-RTKJXNZS.mjs} +32 -9
  137. package/dist/sdk/chunk-RTKJXNZS.mjs.map +1 -0
  138. package/dist/sdk/chunk-VW2GBXQT.mjs +606 -0
  139. package/dist/sdk/chunk-VW2GBXQT.mjs.map +1 -0
  140. package/dist/sdk/{config-RQQPMLRD.mjs → config-5AUYQFHE.mjs} +2 -2
  141. package/dist/sdk/config-6CUVEH7H.mjs +16 -0
  142. package/dist/sdk/config-6CUVEH7H.mjs.map +1 -0
  143. package/dist/sdk/{github-frontend-6Q4BISZX.mjs → github-frontend-BZ4N3BFZ.mjs} +7 -3
  144. package/dist/sdk/github-frontend-BZ4N3BFZ.mjs.map +1 -0
  145. package/dist/sdk/host-4MT3EW2I.mjs +52 -0
  146. package/dist/sdk/{host-P5NQICP7.mjs → host-NYWXLIFC.mjs} +2 -2
  147. package/dist/sdk/host-NYWXLIFC.mjs.map +1 -0
  148. package/dist/sdk/{routing-DEY2AIXM.mjs → routing-6R42GXUO.mjs} +2 -2
  149. package/dist/sdk/routing-6R42GXUO.mjs.map +1 -0
  150. package/dist/sdk/routing-7FXPULTO.mjs +24 -0
  151. package/dist/sdk/routing-7FXPULTO.mjs.map +1 -0
  152. package/dist/sdk/sdk.d.mts +3 -1
  153. package/dist/sdk/sdk.d.ts +3 -1
  154. package/dist/sdk/sdk.js +12163 -11204
  155. package/dist/sdk/sdk.js.map +1 -1
  156. package/dist/sdk/sdk.mjs +14 -10
  157. package/dist/sdk/sdk.mjs.map +1 -1
  158. package/dist/sdk/slack-frontend-JUT3TYVC.mjs +821 -0
  159. package/dist/sdk/slack-frontend-JUT3TYVC.mjs.map +1 -0
  160. package/dist/sdk/workflow-check-provider-H3CUOLUD.mjs +28 -0
  161. package/dist/sdk/workflow-check-provider-H3CUOLUD.mjs.map +1 -0
  162. package/dist/sdk/workflow-check-provider-YUNNF4KC.mjs +28 -0
  163. package/dist/sdk/workflow-check-provider-YUNNF4KC.mjs.map +1 -0
  164. package/dist/sdk/workflow-registry-KFWSDSLM.mjs +12 -0
  165. package/dist/sdk/workflow-registry-KFWSDSLM.mjs.map +1 -0
  166. package/dist/slack/socket-runner.d.ts +2 -0
  167. package/dist/slack/socket-runner.d.ts.map +1 -1
  168. package/dist/state-machine/context/workflow-inputs.d.ts +20 -0
  169. package/dist/state-machine/context/workflow-inputs.d.ts.map +1 -0
  170. package/dist/state-machine/dispatch/execution-invoker.d.ts.map +1 -1
  171. package/dist/state-machine/dispatch/foreach-processor.d.ts.map +1 -1
  172. package/dist/state-machine/dispatch/stats-manager.d.ts.map +1 -1
  173. package/dist/state-machine/states/level-dispatch.d.ts.map +1 -1
  174. package/dist/state-machine/states/routing.d.ts +2 -1
  175. package/dist/state-machine/states/routing.d.ts.map +1 -1
  176. package/dist/traces/{run-2026-01-28T16-15-24-569Z.ndjson → run-2026-01-31T16-37-22-321Z.ndjson} +84 -84
  177. package/dist/traces/{run-2026-01-28T16-16-09-757Z.ndjson → run-2026-01-31T16-38-06-031Z.ndjson} +1013 -1013
  178. package/dist/types/config.d.ts +3 -1
  179. package/dist/types/config.d.ts.map +1 -1
  180. package/dist/utils/human-id.d.ts +12 -0
  181. package/dist/utils/human-id.d.ts.map +1 -0
  182. package/dist/utils/worktree-manager.d.ts +3 -0
  183. package/dist/utils/worktree-manager.d.ts.map +1 -1
  184. package/dist/workflow-executor.d.ts.map +1 -1
  185. package/dist/workflow-registry.d.ts +1 -0
  186. package/dist/workflow-registry.d.ts.map +1 -1
  187. package/package.json +2 -2
  188. package/dist/sdk/chunk-BHZ4CKUS.mjs.map +0 -1
  189. package/dist/sdk/chunk-PVITVJ6J.mjs.map +0 -1
  190. package/dist/sdk/chunk-YLQ4UN62.mjs.map +0 -1
  191. package/dist/sdk/github-frontend-6Q4BISZX.mjs.map +0 -1
  192. /package/dist/sdk/{check-provider-registry-AQ3JETBG.mjs.map → check-provider-registry-3KI5RKXT.mjs.map} +0 -0
  193. /package/dist/sdk/{config-RQQPMLRD.mjs.map → check-provider-registry-IYILYY35.mjs.map} +0 -0
  194. /package/dist/sdk/{routing-DEY2AIXM.mjs.map → config-5AUYQFHE.mjs.map} +0 -0
  195. /package/dist/sdk/{host-P5NQICP7.mjs.map → host-4MT3EW2I.mjs.map} +0 -0
@@ -5,7 +5,7 @@ This doc clarifies how `forEach` output is validated, how it affects dependent c
5
5
  ## Valid and invalid outputs
6
6
 
7
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`
8
+ - Issue: `forEach/execution_error`
9
9
  - Effect: direct dependents are skipped (`dependency_failed`).
10
10
  - If the value is an array, the engine iterates items.
11
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.
@@ -19,7 +19,7 @@ This doc clarifies how `forEach` output is validated, how it affects dependent c
19
19
  forEach: no items from "fetch-tickets", skipping check...
20
20
  ```
21
21
 
22
- - `undefined`: invalid — treated as a configuration/transform error. The engine emits a `forEach/undefined_output` issue and skips direct dependents.
22
+ - `undefined`: invalid — treated as a configuration/transform error. The engine emits a `forEach/execution_error` issue and skips direct dependents.
23
23
 
24
24
  ## Example
25
25
 
@@ -38,7 +38,7 @@ steps:
38
38
  ```
39
39
 
40
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.
41
+ - If `transform_js` returns `undefined`, the engine raises `forEach/execution_error` and `analyze-ticket` is skipped due to a failed dependency.
42
42
 
43
43
  ## Output Access and History with forEach
44
44
 
@@ -62,7 +62,8 @@ steps:
62
62
  depends_on: [process-items]
63
63
  content: |
64
64
  // Access all forEach iteration results
65
- const allProcessed = outputs.history['process-items']; # or outputs_history['process-items']
65
+ // Also available as: outputs_history['process-items']
66
+ const allProcessed = outputs.history['process-items'];
66
67
  return { totalProcessed: allProcessed.length };
67
68
  ```
68
69
 
@@ -168,25 +169,40 @@ checks:
168
169
  group: '...'
169
170
  },
170
171
  attempt: 1, // Attempt number for this check
171
- loop: 2, // Loop number in routing
172
+ loop: 0, // Loop number in routing (starts at 0)
172
173
  outputs: {
173
174
  'extract-facts': [...], // The forEach array
174
175
  'validate-fact': [...], // Latest dependent results
176
+ history: {...} // Same as outputs_history
175
177
  },
176
- outputs.history: {
178
+ outputs_history: {
177
179
  'extract-facts': [[...], ...], // Historical forEach outputs
178
180
  'validate-fact': [[...], ...], // ALL iteration results
179
181
  },
182
+ outputs_raw: {
183
+ 'extract-facts': [...], // Raw outputs without history
184
+ },
180
185
  forEach: {
181
- total: 3, // Number of items processed
182
- successful: 3, // Successful iterations
183
- failed: 0, // Failed iterations
184
- items: [...] // The forEach items array
186
+ items: 3 // Number of items in the forEach array
187
+ },
188
+ memory: { // Memory access functions
189
+ get: (key, ns?) => value,
190
+ has: (key, ns?) => boolean,
191
+ getAll: (ns?) => object,
192
+ set: (key, value, ns?) => void,
193
+ clear: (ns?) => void,
194
+ increment: (key, amount?, ns?) => number
195
+ },
196
+ pr: { // PR metadata
197
+ number: 123,
198
+ title: '...',
199
+ author: '...',
200
+ branch: '...',
201
+ base: '...'
185
202
  },
186
- memory, // Memory access functions
187
- pr, // PR metadata
188
203
  files, // Changed files
189
- env // Environment variables
204
+ env, // Environment variables
205
+ event: { name: '...' } // Event that triggered execution
190
206
  }
191
207
  ```
192
208
 
@@ -256,7 +272,7 @@ checks:
256
272
  log('Validation complete:', {
257
273
  allValid,
258
274
  attempt,
259
- forEach: forEach.total + ' facts checked'
275
+ items: forEach.items + ' facts checked'
260
276
  });
261
277
 
262
278
  if (allValid) {
@@ -392,7 +408,7 @@ This is the **only way** to aggregate across multiple dependent checks after for
392
408
  2. **Use outputs.history**: Access all iteration results with `outputs.history['check-name']`
393
409
  3. **Store in Memory**: Pass aggregated state to `goto_js` and downstream checks via memory
394
410
  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
411
+ 5. **Handle Empty Arrays**: Check `forEach.items` or array length before processing
396
412
  6. **Log Decisions**: Use `log()` in JavaScript to debug routing decisions
397
413
  7. **Check Multiple Dependents**: Perfect for scenarios with multiple dependent checks
398
414
 
@@ -447,6 +463,7 @@ const results = outputs.history['validate-fact'];
447
463
  - [Dependencies](./dependencies.md) - `on_finish` with forEach propagation patterns
448
464
  - [Output History](./output-history.md) - Accessing historical outputs across iterations
449
465
  - [examples/fact-validator.yaml](../examples/fact-validator.yaml) - Complete working example
466
+
450
467
  ## Fan-out Control for Routing (Phase 5)
451
468
 
452
469
  When routing from a forEach context, you can opt into per‑item runs without writing manual loops:
@@ -28,16 +28,17 @@ steps:
28
28
  ```
29
29
 
30
30
  Notes:
31
- - Empty strings are ignored automatically; no `value_js` needed to filter them out.
31
+ - Empty strings are automatically ignored.
32
+ - Values can be a JSON array (rendered via Liquid) or newline-separated list, which will be flattened automatically.
32
33
 
33
34
  ### Issues (Errors) Emitted
34
35
 
35
- When the provider cannot perform an operation, it returns a synthetic issue in the checks output:
36
+ When the provider cannot perform an operation, it returns a synthetic issue in the check's output:
36
37
 
37
- - `github/missing_token` — no token available
38
+ - `github/missing_octokit` — no authenticated Octokit instance available in event context
38
39
  - `github/missing_context` — missing owner/repo/PR number
39
40
  - `github/unsupported_op` — unknown `op`
40
- - `github/value_js_error` — exception thrown while evaluating `value_js`
41
+ - `github/liquid_render_error` — exception thrown while rendering Liquid template in `values`
41
42
  - `github/op_failed` — Octokit call failed (includes error message)
42
43
 
43
44
  These issues are visible in tables/markdown output and will not abort the whole workflow; use `fail_if` to control behavior.
@@ -84,6 +85,6 @@ steps:
84
85
 
85
86
  ## Tips
86
87
 
87
- - Combine Liquid and `value_js` to build dynamic, multilabel operations safely.
88
+ - Use Liquid templates in `values` to build dynamic, multi-label operations safely.
88
89
  - Use `tags: [github]` to run these checks only in Actions (paired with `--tags github`).
89
90
  - Pair with `if:` conditions to gate on prior outputs, e.g., apply labels only when `outputs.overview.tags.label` exists.
@@ -0,0 +1,322 @@
1
+ # Visor Glossary
2
+
3
+ This glossary provides definitions for all key terms and concepts used in Visor. For detailed documentation on specific topics, follow the links to the relevant documentation pages.
4
+
5
+ ## A
6
+
7
+ ### AI Provider
8
+ An integration with a large language model service (Google Gemini, Anthropic Claude, OpenAI GPT, AWS Bedrock) that enables AI-powered code analysis. Configured via `type: ai` in step definitions. See [AI Configuration](./ai-configuration.md).
9
+
10
+ ### `appendPrompt`
11
+ A configuration option that appends additional text to an inherited prompt when using `extends`. The parent and child prompts are joined with a double newline. See [Configuration](./configuration.md).
12
+
13
+ ### `args`
14
+ Input parameter values passed to a workflow when invoking it via `type: workflow`. Also used in `on_init` hooks to pass arguments to tools, steps, or workflows. See [Workflows](./workflows.md).
15
+
16
+ ### `argsTransform`
17
+ A Liquid template that dynamically constructs method arguments for MCP provider calls. See [MCP Provider](./mcp-provider.md).
18
+
19
+ ### `assume`
20
+ A precondition (contract) that must be true before a step executes. If false, the step is skipped with `skipReason='assume'`. Used for pre-execution validation of environment variables, memory values, or upstream outputs. See [Fault Management Guide](./guides/fault-management-and-contracts.md).
21
+
22
+ ## B
23
+
24
+ ### Backoff Policy
25
+ Configuration for retry delays. Supports `fixed` (constant delay) or `exponential` (increasing delay with optional jitter) modes. Configured via `on_fail.retry.backoff`. See [Failure Routing](./failure-routing.md).
26
+
27
+ ## C
28
+
29
+ ### Check
30
+ A single unit of work in a Visor workflow. Each check has a type (provider), configuration, and optional dependencies. The terms "check" and "step" are used interchangeably; `steps:` is the recommended configuration key.
31
+
32
+ ### Check Provider
33
+ A pluggable component that executes a specific type of check. Visor includes 15 built-in providers: `ai`, `claude-code`, `mcp`, `command`, `script`, `http`, `http_input`, `http_client`, `memory`, `noop`, `log`, `github`, `human-input`, `workflow`, and `git-checkout`. See [Pluggable Architecture](./pluggable.md).
34
+
35
+ ### Claude Code Provider
36
+ A provider (`type: claude-code`) that integrates the Claude Code SDK with MCP tools and advanced agent capabilities including subagents and streaming. See [Claude Code](./claude-code.md).
37
+
38
+ ### Command Provider
39
+ A provider (`type: command`) that executes shell commands with Liquid template support. Configured via `exec` field. See [Command Provider](./command-provider.md).
40
+
41
+ ### `continue_on_failure`
42
+ A boolean flag that allows dependent steps to run even if this step fails. Defaults to `false` for critical steps and `true` for `info` criticality. Similar to GitHub Actions' `continue-on-error`. See [Configuration](./configuration.md).
43
+
44
+ ### Contracts
45
+ Design-by-contract primitives (`assume`, `guarantee`, `fail_if`) that define preconditions, postconditions, and failure policies for steps. See [Fault Management Guide](./guides/fault-management-and-contracts.md).
46
+
47
+ ### Criticality
48
+ A classification (`external`, `internal`, `policy`, `info`) that indicates the operational risk level of a step. Drives default safety policies for contracts, retries, loop budgets, and dependency gating. See [Criticality Modes Guide](./guides/criticality-modes.md).
49
+
50
+ #### Criticality Levels
51
+
52
+ | Level | Description | Use When |
53
+ |-------|-------------|----------|
54
+ | `external` | Mutates external systems (GitHub, HTTP POST, file writes) | Step has side effects outside the engine |
55
+ | `internal` | Steers execution (forEach, routing, flags) | Step controls workflow routing |
56
+ | `policy` | Enforces permissions or compliance | Step gates external actions |
57
+ | `info` | Read-only, non-critical | Pure computation, safe to fail |
58
+
59
+ ### Custom Tools
60
+ User-defined MCP tools specified in the `tools:` section of configuration. Can be invoked via `transport: custom` in MCP checks or in `on_init` hooks. See [Custom Tools](./custom-tools.md).
61
+
62
+ ## D
63
+
64
+ ### Dependency Graph
65
+ The internal data structure that tracks dependencies between steps, used to determine execution order. Steps declare dependencies via `depends_on`.
66
+
67
+ ### `depends_on`
68
+ A field that declares which steps must complete before this step runs. Accepts a single string or array of step names. See [Configuration](./configuration.md).
69
+
70
+ ## E
71
+
72
+ ### Engine
73
+ The execution runtime that orchestrates step execution based on dependencies, events, and routing rules. Operates in either `legacy` or `state-machine` mode.
74
+
75
+ ### Engine State
76
+ The current phase of execution in the state machine engine. States include: `Init`, `PlanReady`, `WavePlanning`, `LevelDispatch`, `CheckRunning`, `Routing`, `Completed`, and `Error`.
77
+
78
+ ### Event Trigger
79
+ A condition that determines when a step runs. Valid triggers: `pr_opened`, `pr_updated`, `pr_closed`, `issue_opened`, `issue_comment`, `manual`, `schedule`, `webhook_received`. Configured via the `on:` field. See [Event Triggers](./event-triggers.md).
80
+
81
+ ### Execution Context
82
+ The runtime environment provided to step execution, including PR information, outputs from dependencies, memory store access, and environment variables.
83
+
84
+ ### `extends`
85
+ A configuration option that inherits settings from another configuration file (local path, HTTP URL, or `default`). Supports single or multiple extends with merge semantics. See [Configuration](./configuration.md).
86
+
87
+ ## F
88
+
89
+ ### `fail_if`
90
+ A JavaScript expression that marks a step as failed when it evaluates to true. Used for policy and threshold decisions. Triggers `on_fail` routing. See [Fail If](./fail-if.md).
91
+
92
+ ### Failure Routing
93
+ Configuration (`on_fail`) that defines how to handle step failures, including retry policies, remediation steps (`run`), and jump-back routing (`goto`). See [Failure Routing](./failure-routing.md).
94
+
95
+ ### Fanout
96
+ The `fanout` field controls how routing targets behave when invoked from a `forEach` context. `map` schedules once per item; `reduce` schedules a single aggregation run. See [Failure Routing](./failure-routing.md).
97
+
98
+ ### `forEach`
99
+ A boolean flag that processes a step's output as an array, running dependent steps once per item. Enables parallel processing and iteration patterns. See [Failure Routing](./failure-routing.md).
100
+
101
+ ### Frontends
102
+ Event-driven integration points that trigger Visor workflows. Includes GitHub (webhooks) and Slack (Socket Mode). Configured via `frontends:` section. See [Slack Integration](./slack-integration.md).
103
+
104
+ ## G
105
+
106
+ ### Git-Checkout Provider
107
+ A provider (`type: git-checkout`) that checks out code from git repositories using efficient worktree management. Supports cross-repository comparisons. See [Git Checkout](./providers/git-checkout.md).
108
+
109
+ ### GitHub Provider
110
+ A provider (`type: github`) that interacts with the GitHub API for operations like adding labels, creating comments, and managing status checks. See [Configuration](./configuration.md).
111
+
112
+ ### `goto`
113
+ A routing directive that jumps back to a previously executed ancestor step. Used in `on_success`, `on_fail`, and `on_finish` hooks. See [Failure Routing](./failure-routing.md).
114
+
115
+ ### `goto_event`
116
+ An event override used with `goto` to simulate a different event during the jump. For example, jumping to a PR step from an issue comment flow while treating it as `pr_updated`. See [Event Triggers](./event-triggers.md).
117
+
118
+ ### `goto_js`
119
+ A JavaScript expression that dynamically computes the target step for a `goto`. Returns a step ID string or `null` to skip routing. See [Failure Routing](./failure-routing.md).
120
+
121
+ ### `guarantee`
122
+ A postcondition (contract) that must hold after a step completes. Violations add `contract/guarantee_failed` issues and route via `on_fail`. Used for assertions about produced output shape and values. See [Fault Management Guide](./guides/fault-management-and-contracts.md).
123
+
124
+ ### Group
125
+ A logical grouping for steps that controls how results are organized in PR comments. Steps with the same `group` value appear together. Configured via the `group:` field.
126
+
127
+ ## H
128
+
129
+ ### HTTP Client Provider
130
+ A provider (`type: http_client`) that makes HTTP requests to external APIs and returns the response for use by dependent steps. See [HTTP Integration](./http.md).
131
+
132
+ ### HTTP Input Provider
133
+ A provider (`type: http_input`) that receives incoming webhooks at a configured endpoint. Triggers the `webhook_received` event. See [HTTP Integration](./http.md).
134
+
135
+ ### HTTP Provider
136
+ A provider (`type: http`) that sends check results to external webhooks. Used for notifications and integrations. See [HTTP Integration](./http.md).
137
+
138
+ ### Human Input Provider
139
+ A provider (`type: human-input`) that pauses workflow execution to request input from a user. In Slack, consumes thread messages; in CLI, prompts for input. See [Human Input Provider](./human-input-provider.md).
140
+
141
+ ## I
142
+
143
+ ### `if`
144
+ A JavaScript expression that determines whether a step should run. Evaluated at scheduling time; if false, the step is skipped. See [Configuration](./configuration.md).
145
+
146
+ ### `imports`
147
+ A configuration field that loads workflow definitions from external files or URLs. Imported workflows can be invoked via `type: workflow`. See [Workflows](./workflows.md).
148
+
149
+ ### Issue
150
+ A detected problem or suggestion from a check. Has properties like `file`, `line`, `message`, `severity`, `category`, and `ruleId`. Collected and displayed in PR comments or output formats.
151
+
152
+ ## J
153
+
154
+ ### Journal
155
+ The execution journal that records all check results, routing decisions, and state transitions. Used for debugging, auditing, and snapshot persistence.
156
+
157
+ ## L
158
+
159
+ ### Lifecycle Hooks
160
+ Four hooks that control step execution at different phases: `on_init` (before), `on_success` (after success), `on_fail` (after failure), `on_finish` (after all forEach iterations). See [Lifecycle Hooks](./lifecycle-hooks.md).
161
+
162
+ ### Limits
163
+ Global execution constraints configured via `limits:`. Includes `max_runs_per_check` (default 50) and `max_workflow_depth` (default 3). See [Limits](./limits.md).
164
+
165
+ ### Liquid Templates
166
+ A templating language used throughout Visor for dynamic values in prompts, commands, HTTP bodies, and transforms. Provides access to `pr`, `files`, `outputs`, `memory`, and `env` contexts. See [Liquid Templates](./liquid-templates.md).
167
+
168
+ ### Log Provider
169
+ A provider (`type: log`) that outputs messages for debugging and workflow visibility. Supports message templates, log levels, and context inclusion. See [Debugging](./debugging.md).
170
+
171
+ ### Loop Budget
172
+ The `routing.max_loops` setting that caps routing transitions (goto + run) per scope. Default is 10; recommended 8 for control-plane flows. Prevents infinite loops. See [Failure Routing](./failure-routing.md).
173
+
174
+ ## M
175
+
176
+ ### MCP (Model Context Protocol)
177
+ A protocol for AI tools that enables models to interact with external systems. Visor supports MCP via the `mcp` provider (direct tool calls) and within AI providers (enhancing AI with tools). See [MCP Provider](./mcp-provider.md) and [MCP Tools](./mcp.md).
178
+
179
+ ### Memory Provider
180
+ A provider (`type: memory`) that provides persistent key-value storage across checks. Supports operations: `get`, `set`, `append`, `increment`, `delete`, `clear`, `list`. Enables stateful workflows. See [Memory](./memory.md).
181
+
182
+ ### Memory Store
183
+ The runtime storage system accessible via the `memory` object in JavaScript expressions and Liquid templates. Supports namespaces for isolation. See [Memory](./memory.md).
184
+
185
+ ## N
186
+
187
+ ### Namespace
188
+ A memory isolation context that separates key-value data between different workflows or concerns. Configured via `memory.namespace` globally or `namespace:` per step.
189
+
190
+ ### Noop Provider
191
+ A provider (`type: noop`) that performs no operation. Used for dependency triggering, control flow, and routing-only steps. See [Noop Provider](./providers/noop.md).
192
+
193
+ ## O
194
+
195
+ ### `on_fail`
196
+ A lifecycle hook that runs after a step fails. Supports `retry`, `run` (remediation steps), `goto` (jump-back), and dynamic variants (`run_js`, `goto_js`). See [Lifecycle Hooks](./lifecycle-hooks.md).
197
+
198
+ ### `on_finish`
199
+ A lifecycle hook for `forEach` steps that runs once after all iterations and all dependent checks complete. Used for aggregation and validation across all items. See [Lifecycle Hooks](./lifecycle-hooks.md).
200
+
201
+ ### `on_init`
202
+ A lifecycle hook that runs before a step executes. Used for preprocessing, data fetching, and context enrichment. Can invoke tools, steps, or workflows. See [Lifecycle Hooks](./lifecycle-hooks.md).
203
+
204
+ ### `on_success`
205
+ A lifecycle hook that runs after a step completes successfully. Supports `run` (post-processing steps), `goto` (routing), and dynamic variants. See [Lifecycle Hooks](./lifecycle-hooks.md).
206
+
207
+ ### Output
208
+ The result produced by a step, accessible via `outputs['step-name']` in subsequent steps. Can be transformed via `transform` or `transform_js`. See [Output History](./output-history.md).
209
+
210
+ ### Output History
211
+ The `outputs.history` or `outputs_history` accessor that provides all historical values for a step across loop iterations. Used in routing decisions and aggregation. See [Output History](./output-history.md).
212
+
213
+ ### Output Mapping
214
+ The `output_mapping` field in workflow invocations that maps workflow output names to check output names. See [Workflows](./workflows.md).
215
+
216
+ ## P
217
+
218
+ ### Provider
219
+ See [Check Provider](#check-provider).
220
+
221
+ ### PR Context
222
+ The pull request information available in templates and expressions: `pr.number`, `pr.title`, `pr.author`, `pr.branch`, `pr.base`, etc. Also includes `files` (changed files) and `fileCount`.
223
+
224
+ ## R
225
+
226
+ ### Retry Policy
227
+ Configuration for automatic retries on step failure. Includes `max` (maximum attempts) and `backoff` (delay strategy). Configured via `on_fail.retry`. See [Failure Routing](./failure-routing.md).
228
+
229
+ ### Routing
230
+ The system for controlling workflow execution flow via `goto`, `run`, and `transitions`. Enables loops, remediation, and dynamic execution paths. See [Failure Routing](./failure-routing.md) and [Router Patterns](./router-patterns.md).
231
+
232
+ ### `run`
233
+ A routing directive that executes specified steps. Used in `on_init`, `on_success`, `on_fail`, and `on_finish` hooks. See [Lifecycle Hooks](./lifecycle-hooks.md).
234
+
235
+ ### `run_js`
236
+ A JavaScript expression that dynamically computes which steps to run. Returns a string array of step IDs. See [Failure Routing](./failure-routing.md).
237
+
238
+ ## S
239
+
240
+ ### Schema
241
+ The `schema` field that specifies output format and validation. String values select template renderers (e.g., `code-review`, `markdown`). Object values provide JSON Schema for output validation. See [Configuration](./configuration.md).
242
+
243
+ ### Scope
244
+ An execution context that tracks loop counters, attempt numbers, and forEach item indexes. Each forEach item creates a child scope. Used for isolation and loop budget enforcement.
245
+
246
+ ### Script Provider
247
+ A provider (`type: script`) that executes JavaScript in a secure sandbox with access to PR context, outputs, memory, and environment. Configured via `content` field. See [Script](./script.md).
248
+
249
+ ### Session
250
+ An AI conversation context that can be reused across steps via `reuse_ai_session`. Supports `clone` (copy history) or `append` (share history) modes.
251
+
252
+ ### Slack Integration
253
+ Bidirectional Slack integration via Socket Mode that enables chat assistants, human input collection, and notifications. Configured via `slack:` section and `--slack` flag. See [Slack Integration](./slack-integration.md).
254
+
255
+ ### Snapshot
256
+ A serialized state of workflow execution stored in the journal. Enables debugging, replay, and session resume.
257
+
258
+ ### State Machine
259
+ The execution engine mode (`mode: 'state-machine'`) that processes steps in waves with sophisticated routing and loop control. The default for modern Visor workflows.
260
+
261
+ ### Step
262
+ See [Check](#check). The recommended term and configuration key (`steps:` instead of `checks:`).
263
+
264
+ ### Suppression
265
+ The ability to disable specific issues via inline comments (`// visor-disable: rule-id`). Controlled by `output.suppressionEnabled`. See [Suppressions](./suppressions.md).
266
+
267
+ ## T
268
+
269
+ ### Tags
270
+ Labels attached to steps for categorization and filtering. Common patterns: `local`/`remote`, `fast`/`slow`, `security`, `experimental`. Configured via `tags:` field. See [Tag Filtering](./tag-filtering.md).
271
+
272
+ ### Tag Filter
273
+ Configuration (`tag_filter:` or `--tags`/`--exclude-tags`) that selectively runs steps based on their tags. Supports `include` and `exclude` arrays. See [Tag Filtering](./tag-filtering.md).
274
+
275
+ ### Telemetry
276
+ OpenTelemetry-based tracing and metrics for debugging and observability. Configurable via environment variables or `telemetry:` section. Supports OTLP, file, and console sinks. See [Telemetry Setup](./telemetry-setup.md).
277
+
278
+ ### Transform
279
+ The `transform` (Liquid) or `transform_js` (JavaScript) fields that modify step output before it's stored and passed to dependents. See [MCP Provider](./mcp-provider.md).
280
+
281
+ ### Transitions
282
+ Declarative routing rules in `on_success`, `on_fail`, or `on_finish` blocks. Each rule has `when` (condition), `to` (target step), and optional `goto_event`. Evaluated in order; first match wins. See [Failure Routing](./failure-routing.md).
283
+
284
+ ## V
285
+
286
+ ### Validate Command
287
+ The `visor validate` CLI command that checks configuration files for errors before running. Validates schema compliance, check types, and event triggers. See [Configuration](./configuration.md).
288
+
289
+ ### Visor
290
+ An AI-powered workflow orchestration tool for code review and automation. Runs as a GitHub Action or CLI tool.
291
+
292
+ ## W
293
+
294
+ ### Wave
295
+ A batch of steps executed in parallel during a single phase of the state machine. The engine processes waves iteratively based on the dependency graph and routing decisions.
296
+
297
+ ### Webhook
298
+ An HTTP endpoint that receives external events. Configured via `http_server:` for incoming webhooks and `type: http` for outgoing notifications. See [HTTP Integration](./http.md).
299
+
300
+ ### Workflow
301
+ A reusable, parameterized sequence of steps that can be invoked via `type: workflow`. Defined in separate files with `inputs`, `outputs`, and `steps`. Imported via the `imports:` field. See [Workflows](./workflows.md).
302
+
303
+ ### Workflow Composition
304
+ The pattern of workflows invoking other workflows. Supports nested execution up to `limits.max_workflow_depth` (default 3). See [Workflows](./workflows.md).
305
+
306
+ ### Workflow Provider
307
+ A provider (`type: workflow`) that executes a reusable workflow definition. Supports `args`, `overrides`, and `output_mapping`. See [Workflows](./workflows.md).
308
+
309
+ ### Workspace
310
+ An isolated execution environment for workflows. Configured via `workspace:` section. Provides sandboxed file system access. See [Workspace Isolation RFC](./rfc/workspace-isolation.md).
311
+
312
+ ---
313
+
314
+ ## See Also
315
+
316
+ - [Configuration Reference](./configuration.md)
317
+ - [Pluggable Architecture](./pluggable.md)
318
+ - [Event Triggers](./event-triggers.md)
319
+ - [Lifecycle Hooks](./lifecycle-hooks.md)
320
+ - [Failure Routing](./failure-routing.md)
321
+ - [Workflows](./workflows.md)
322
+ - [Debugging](./debugging.md)
@@ -1,5 +1,7 @@
1
1
  # Visor Engine Plan: Use `goto` for Looping on Failures
2
2
 
3
+ **Status: IMPLEMENTED** (Core features complete; `one_shot` tag not yet implemented)
4
+
3
5
  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
6
 
5
7
  ## Background
@@ -34,7 +36,7 @@ The engine should handle re‑running the necessary chain; YAML should not list
34
36
 
35
37
  4) Loop safety and predictability
36
38
  - 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.
39
+ - **NOT YET IMPLEMENTED**: Respect `one_shot` tag: skip re‑running steps with `tags: [one_shot]` that already executed in this run.
38
40
  - Maintain per‑run statistics to avoid duplicate scheduling within a wave.
39
41
 
40
42
  5) Forward‑run details
@@ -81,16 +83,23 @@ Pattern B (single hop to anchor):
81
83
 
82
84
  ## Code Pointers
83
85
 
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.
86
+ **Note:** The implementation now uses a state machine architecture. The original
87
+ `check-execution-engine.ts` is a compatibility layer that re-exports from
88
+ `state-machine-execution-engine.ts`.
89
+
90
+ Key files in `src/state-machine/states/`:
91
+ - `routing.ts` — handles `on_fail.run/goto` and `on_success.run/goto`:
92
+ - `processOnSuccess()` and `processOnFail()` emit `ForwardRunRequested` events
93
+ - Both use the same `evaluateGoto()` helper for unified behavior
94
+ - `wave-planning.ts` — processes forward-run requests:
95
+ - Builds dependency subgraph and computes topological order
96
+ - Detects cycles in forward-run dependency subset
97
+ - Queues levels for execution
98
+ - `level-dispatch.ts` — executes checks and respects `if` conditions
90
99
 
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.
100
+ Guards:
101
+ - `routing.max_loops` budget is enforced in `routing.ts` via `checkLoopBudget()`
102
+ - Per-wave deduplication handled in `wave-planning.ts`
94
103
 
95
104
  ## Telemetry / Debug
96
105
  - Add concise debug logs for `goto` forward‑run across all origins: target, number of dependents, topological order.
@@ -111,3 +120,7 @@ Suggested refactor:
111
120
  - Single‑run multi‑refine test passes with exact counts.
112
121
  - Flow multi‑refine tests pass.
113
122
  - No regression in existing suites; loop budget respected.
123
+
124
+ **Test Coverage:**
125
+ - `tests/integration/goto-forward-run-integration.test.ts` — verifies goto + goto_event forward-run
126
+ - `tests/unit/forward-goto-cycle-detection.test.ts` — verifies cycle detection in forward-run subset
@@ -1,4 +1,4 @@
1
- # Criticality Modes — External, Control‑Plane, Policy, Non‑Critical
1
+ # Criticality Modes — external, internal, policy, info
2
2
 
3
3
  This document explains what each criticality mode means, how to declare it, the engine defaults it enables, and how core constructs (if, assume, guarantee, fail_if, transitions, retries, loop budgets) behave per mode. All examples use block‑style YAML.
4
4
 
@@ -26,13 +26,15 @@ checks:
26
26
  criticality: internal # external | internal | policy | info
27
27
  ```
28
28
 
29
- If the field is omitted, the engine may infer a default (mutating → external; forEach parent or on_* goto/run → control‑plane; policy gates → policy; else non‑critical). You can override any default on a per‑check basis.
29
+ If the field is omitted, the engine defaults to `policy`. You can override this default on a per‑check basis.
30
30
 
31
31
  ### Mode selection — quick checklist
32
- - Does this step mutate external state? → external
33
- - Does it steer execution (fan‑out, transitions/goto, sets flags for other guards)? → internal
34
- - Does it enforce permissions/policy/compliance and gate external steps? → policy
35
- - Otherwise, is it read‑only/pure and low‑risk? → info
32
+ - Does this step mutate external state (GitHub ops, HTTP POST/PUT, file writes)? → `external`
33
+ - Does it steer execution (fan‑out, transitions/goto, sets flags for other guards)? → `internal`
34
+ - Does it enforce permissions/policy/compliance and gate external steps? → `policy`
35
+ - Otherwise, is it read‑only/pure and low‑risk? → `info`
36
+
37
+ **Note:** When `criticality` is omitted, the engine defaults to `policy`.
36
38
 
37
39
  If in doubt, start with info and promote to policy/internal/external when you add gating, routing, or side‑effects.
38
40
 
@@ -80,9 +82,9 @@ checks:
80
82
 
81
83
  ---
82
84
 
83
- ## Control‑Plane
85
+ ## Internal (Control‑Plane)
84
86
 
85
- Steers execution (decides what runs next and how often). Examples: forEach parents, steps with on_* transitions/goto/run, memory/flags used by conditions.
87
+ Steers execution (decides what runs next and how often). Examples: forEach parents, steps with on_* transitions/goto/run, memory/flags used by conditions. Use `criticality: internal` to designate these steps.
86
88
 
87
89
  Defaults
88
90
  - Contracts required (route integrity): meaningful `assume` and `guarantee`.
@@ -126,7 +128,7 @@ checks:
126
128
  exec: node scripts/fix.js
127
129
  ```
128
130
 
129
- ### When to pick CONTROL‑PLANE (real‑life)
131
+ ### When to pick INTERNAL (real‑life)
130
132
  - A forEach parent that fans out work to child steps (e.g., facts, files, services, directories, modules).
131
133
  - An aggregator that computes a run decision (`all_valid`, `needs_retry`, `next_targets`) and routes via transitions.
132
134
  - A small `memory`/`log`/`script` step that sets flags used by `if/assume/guarantee` on other checks (e.g., `needs_retry=true`).
@@ -175,13 +177,13 @@ checks:
175
177
 
176
178
  ---
177
179
 
178
- ## Non‑Critical
180
+ ## Info (Non‑Critical)
179
181
 
180
- Pure/read‑only compute where failures dont risk unsafe behavior.
182
+ Pure/read‑only compute where failures don't risk unsafe behavior. Use `criticality: info` to designate these steps.
181
183
 
182
184
  Defaults
183
185
  - Contracts recommended (not mandatory).
184
- - Gating: `continue_on_failure: true` allowed if safe.
186
+ - Gating: `continue_on_failure` defaults to `true` when `criticality: info` is set (dependents may run even if this step fails).
185
187
  - Retries: bounded; can be slightly looser.
186
188
 
187
189
  Example — summary step that won’t block the pipeline
@@ -197,7 +199,7 @@ checks:
197
199
  fail_if: "(output.errors || []).length > 0"
198
200
  ```
199
201
 
200
- ### When to pick NON‑CRITICAL (real‑life)
202
+ ### When to pick INFO (real‑life)
201
203
  - Read‑only analysis and summaries (lint, style, performance hints, PR summary) where failure should not block critical tasks.
202
204
  - Exploratory AI steps that help humans but don’t gate or mutate (draft review comments in dry‑run; heuristics, suggestions).
203
205
  - Any leaf computation whose outputs aren’t consumed by control‑plane or external steps.
@@ -731,8 +731,11 @@ Highlights
731
731
  - permission-check (policy) gates external actions without itself mutating external systems.
732
732
  - post-comment (external) uses both `if` (early prune) and `assume` (preflight) plus a `guarantee` after posting.
733
733
  - summarize shows a non‑critical step with soft failure handling via `continue_on_failure: true`.
734
- ```
735
- - JSON Schema validation (unified `schema`)
736
- - `schema: <string>` selects layout/renderer (no validation).
737
- - `schema: <object>` is a JSON Schema; the engine validates `output` for any provider (ai/command/script/http). Violations create `contract/schema_validation_failed` and follow criticality rules.
738
- - `output_schema` is deprecated; keep it only for backward compatibility.
734
+
735
+ ## JSON Schema Validation (unified `schema`)
736
+
737
+ The `schema` field has been unified to handle both template selection and output validation:
738
+
739
+ - `schema: <string>` selects a layout/renderer (e.g., `'code-review'`, `'markdown'`) for template rendering.
740
+ - `schema: <object>` is a JSON Schema; the engine validates `output` for any provider (ai/command/script/http). Violations create `contract/schema_validation_failed` issues and follow criticality rules.
741
+ - `output_schema` is deprecated; keep it only for backward compatibility. When both `schema` (object) and `output_schema` are present, `schema` takes precedence for validation.