@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.
- package/dist/config.d.ts.map +1 -1
- package/dist/docs/DEPLOYMENT.md +117 -11
- package/dist/docs/GITHUB_CHECKS.md +18 -4
- package/dist/docs/NPM_USAGE.md +112 -39
- package/dist/docs/action-reference.md +63 -9
- package/dist/docs/advanced-ai.md +58 -51
- package/dist/docs/ai-configuration.md +99 -11
- package/dist/docs/ai-custom-tools-usage.md +70 -33
- package/dist/docs/ai-custom-tools.md +50 -27
- package/dist/docs/architecture.md +1232 -0
- package/dist/docs/bot-transports-rfc.md +13 -3
- package/dist/docs/ci-cli-mode.md +116 -8
- package/dist/docs/claude-code.md +111 -41
- package/dist/docs/command-provider.md +37 -15
- package/dist/docs/commands.md +252 -6
- package/dist/docs/configuration.md +138 -4
- package/dist/docs/contributing.md +737 -0
- package/dist/docs/custom-tools.md +39 -8
- package/dist/docs/dashboards/README.md +33 -19
- package/dist/docs/debug-visualizer-progress.md +14 -13
- package/dist/docs/debug-visualizer-rfc.md +14 -13
- package/dist/docs/debug-visualizer.md +30 -5
- package/dist/docs/debugging.md +73 -8
- package/dist/docs/default-output-schema.md +24 -20
- package/dist/docs/dependencies.md +75 -21
- package/dist/docs/dev-playbook.md +85 -9
- package/dist/docs/engine-pause-resume-rfc.md +11 -11
- package/dist/docs/engine-state-machine-plan.md +10 -3
- package/dist/docs/event-driven-github-integration-rfc.md +20 -11
- package/dist/docs/event-triggers.md +95 -6
- package/dist/docs/execution-statistics-rfc.md +16 -4
- package/dist/docs/fact-validator-gap-analysis.md +12 -1
- package/dist/docs/fact-validator-implementation-plan.md +19 -11
- package/dist/docs/fail-if.md +116 -11
- package/dist/docs/failure-conditions-implementation.md +40 -6
- package/dist/docs/failure-conditions-schema.md +243 -87
- package/dist/docs/failure-routing-rfc.md +43 -18
- package/dist/docs/failure-routing.md +80 -23
- package/dist/docs/faq.md +836 -0
- package/dist/docs/foreach-dependency-propagation.md +32 -15
- package/dist/docs/github-ops.md +6 -5
- package/dist/docs/glossary.md +322 -0
- package/dist/docs/goto-forward-run-plan.md +23 -10
- package/dist/docs/guides/criticality-modes.md +15 -13
- package/dist/docs/guides/fault-management-and-contracts.md +8 -5
- package/dist/docs/guides/workflow-style-guide.md +17 -8
- package/dist/docs/http.md +102 -3
- package/dist/docs/human-input-provider.md +20 -36
- package/dist/docs/index.md +206 -0
- package/dist/docs/lifecycle-hooks.md +322 -2
- package/dist/docs/limits.md +20 -5
- package/dist/docs/liquid-templates.md +86 -14
- package/dist/docs/loop-routing-refactor.md +4 -2
- package/dist/docs/mcp-provider.md +53 -19
- package/dist/docs/mcp.md +27 -1
- package/dist/docs/memory.md +7 -2
- package/dist/docs/migration.md +596 -0
- package/dist/docs/observability.md +227 -6
- package/dist/docs/output-formats.md +388 -9
- package/dist/docs/output-history.md +36 -6
- package/dist/docs/performance.md +510 -4
- package/dist/docs/pluggable.md +95 -4
- package/dist/docs/proposals/snapshot-scope-execution.md +6 -5
- package/dist/docs/providers/git-checkout.md +16 -14
- package/dist/docs/providers/noop.md +696 -0
- package/dist/docs/recipes.md +8 -9
- package/dist/docs/rfc/git-checkout-step.md +3 -1
- package/dist/docs/rfc/on_init-hook.md +18 -5
- package/dist/docs/rfc/workspace-isolation.md +16 -0
- package/dist/docs/roadmap/criticality-implementation-tasks.md +27 -27
- package/dist/docs/router-patterns.md +155 -43
- package/dist/docs/schema-templates.md +51 -15
- package/dist/docs/script.md +162 -13
- package/dist/docs/sdk.md +46 -12
- package/dist/docs/security.md +464 -5
- package/dist/docs/slack-integration.md +481 -0
- package/dist/docs/tag-filtering.md +60 -20
- package/dist/docs/telemetry-setup.md +157 -46
- package/dist/docs/test-framework-rfc.md +37 -36
- package/dist/docs/testing/assertions.md +92 -4
- package/dist/docs/testing/ci.md +56 -7
- package/dist/docs/testing/cli.md +57 -15
- package/dist/docs/testing/cookbook.md +53 -20
- package/dist/docs/testing/dsl-reference.md +110 -9
- package/dist/docs/testing/fixtures-and-mocks.md +28 -3
- package/dist/docs/testing/flows.md +59 -4
- package/dist/docs/testing/getting-started.md +14 -13
- package/dist/docs/testing/troubleshooting.md +39 -2
- package/dist/docs/timeouts.md +174 -18
- package/dist/docs/troubleshooting.md +176 -6
- package/dist/docs/workflow-creation-guide.md +101 -3
- package/dist/docs/workflows.md +138 -41
- package/dist/examples/README.md +169 -4
- package/dist/examples/ai-custom-tools-simple.yaml +2 -3
- package/dist/examples/cron-webhook-config.yaml +15 -0
- package/dist/examples/forEach-example.yaml +6 -0
- package/dist/examples/git-checkout-basic.yaml +4 -0
- package/dist/examples/git-checkout-compare.yaml +6 -0
- package/dist/examples/git-checkout-cross-repo.yaml +7 -0
- package/dist/examples/http-integration-config.yaml +30 -0
- package/dist/examples/https-server-config.yaml +15 -0
- package/dist/examples/mcp-provider-example.yaml +10 -10
- package/dist/examples/transform-example.yaml +3 -0
- package/dist/examples/webhook-pipeline-config.yaml +18 -0
- package/dist/examples/workflows/workflow-composition-example.yaml +4 -0
- package/dist/frontends/slack-frontend.d.ts +2 -0
- package/dist/frontends/slack-frontend.d.ts.map +1 -1
- package/dist/generated/config-schema.d.ts +11 -7
- package/dist/generated/config-schema.d.ts.map +1 -1
- package/dist/generated/config-schema.json +11 -7
- package/dist/index.js +3127 -974
- package/dist/output/traces/{run-2026-01-28T16-15-24-569Z.ndjson → run-2026-01-31T16-37-22-321Z.ndjson} +84 -84
- package/dist/output/traces/{run-2026-01-28T16-16-09-757Z.ndjson → run-2026-01-31T16-38-06-031Z.ndjson} +1013 -1013
- package/dist/providers/ai-check-provider.d.ts +9 -2
- package/dist/providers/ai-check-provider.d.ts.map +1 -1
- package/dist/providers/command-check-provider.d.ts.map +1 -1
- package/dist/providers/mcp-custom-sse-server.d.ts +17 -1
- package/dist/providers/mcp-custom-sse-server.d.ts.map +1 -1
- package/dist/providers/workflow-check-provider.d.ts.map +1 -1
- package/dist/providers/workflow-tool-executor.d.ts +68 -0
- package/dist/providers/workflow-tool-executor.d.ts.map +1 -0
- package/dist/sdk/{check-provider-registry-AQ3JETBG.mjs → check-provider-registry-3KI5RKXT.mjs} +6 -5
- package/dist/sdk/check-provider-registry-IYILYY35.mjs +28 -0
- package/dist/sdk/chunk-2CPMMNIX.mjs +1459 -0
- package/dist/sdk/chunk-2CPMMNIX.mjs.map +1 -0
- package/dist/sdk/chunk-5LI6T4O3.mjs +3600 -0
- package/dist/sdk/chunk-5LI6T4O3.mjs.map +1 -0
- package/dist/sdk/{chunk-YLQ4UN62.mjs → chunk-A4PGHURG.mjs} +6838 -6257
- package/dist/sdk/chunk-A4PGHURG.mjs.map +1 -0
- package/dist/sdk/chunk-EXFGO4FX.mjs +147 -0
- package/dist/sdk/chunk-EXFGO4FX.mjs.map +1 -0
- package/dist/sdk/chunk-PJ7K5UFC.mjs +17732 -0
- package/dist/sdk/chunk-PJ7K5UFC.mjs.map +1 -0
- package/dist/sdk/{chunk-BHZ4CKUS.mjs → chunk-PXFIALUH.mjs} +77 -8
- package/dist/sdk/chunk-PXFIALUH.mjs.map +1 -0
- package/dist/sdk/{chunk-PVITVJ6J.mjs → chunk-RTKJXNZS.mjs} +32 -9
- package/dist/sdk/chunk-RTKJXNZS.mjs.map +1 -0
- package/dist/sdk/chunk-VW2GBXQT.mjs +606 -0
- package/dist/sdk/chunk-VW2GBXQT.mjs.map +1 -0
- package/dist/sdk/{config-RQQPMLRD.mjs → config-5AUYQFHE.mjs} +2 -2
- package/dist/sdk/config-6CUVEH7H.mjs +16 -0
- package/dist/sdk/config-6CUVEH7H.mjs.map +1 -0
- package/dist/sdk/{github-frontend-6Q4BISZX.mjs → github-frontend-BZ4N3BFZ.mjs} +7 -3
- package/dist/sdk/github-frontend-BZ4N3BFZ.mjs.map +1 -0
- package/dist/sdk/host-4MT3EW2I.mjs +52 -0
- package/dist/sdk/{host-P5NQICP7.mjs → host-NYWXLIFC.mjs} +2 -2
- package/dist/sdk/host-NYWXLIFC.mjs.map +1 -0
- package/dist/sdk/{routing-DEY2AIXM.mjs → routing-6R42GXUO.mjs} +2 -2
- package/dist/sdk/routing-6R42GXUO.mjs.map +1 -0
- package/dist/sdk/routing-7FXPULTO.mjs +24 -0
- package/dist/sdk/routing-7FXPULTO.mjs.map +1 -0
- package/dist/sdk/sdk.d.mts +3 -1
- package/dist/sdk/sdk.d.ts +3 -1
- package/dist/sdk/sdk.js +12163 -11204
- package/dist/sdk/sdk.js.map +1 -1
- package/dist/sdk/sdk.mjs +14 -10
- package/dist/sdk/sdk.mjs.map +1 -1
- package/dist/sdk/slack-frontend-JUT3TYVC.mjs +821 -0
- package/dist/sdk/slack-frontend-JUT3TYVC.mjs.map +1 -0
- package/dist/sdk/workflow-check-provider-H3CUOLUD.mjs +28 -0
- package/dist/sdk/workflow-check-provider-H3CUOLUD.mjs.map +1 -0
- package/dist/sdk/workflow-check-provider-YUNNF4KC.mjs +28 -0
- package/dist/sdk/workflow-check-provider-YUNNF4KC.mjs.map +1 -0
- package/dist/sdk/workflow-registry-KFWSDSLM.mjs +12 -0
- package/dist/sdk/workflow-registry-KFWSDSLM.mjs.map +1 -0
- package/dist/slack/socket-runner.d.ts +2 -0
- package/dist/slack/socket-runner.d.ts.map +1 -1
- package/dist/state-machine/context/workflow-inputs.d.ts +20 -0
- package/dist/state-machine/context/workflow-inputs.d.ts.map +1 -0
- package/dist/state-machine/dispatch/execution-invoker.d.ts.map +1 -1
- package/dist/state-machine/dispatch/foreach-processor.d.ts.map +1 -1
- package/dist/state-machine/dispatch/stats-manager.d.ts.map +1 -1
- package/dist/state-machine/states/level-dispatch.d.ts.map +1 -1
- package/dist/state-machine/states/routing.d.ts +2 -1
- package/dist/state-machine/states/routing.d.ts.map +1 -1
- package/dist/traces/{run-2026-01-28T16-15-24-569Z.ndjson → run-2026-01-31T16-37-22-321Z.ndjson} +84 -84
- package/dist/traces/{run-2026-01-28T16-16-09-757Z.ndjson → run-2026-01-31T16-38-06-031Z.ndjson} +1013 -1013
- package/dist/types/config.d.ts +3 -1
- package/dist/types/config.d.ts.map +1 -1
- package/dist/utils/human-id.d.ts +12 -0
- package/dist/utils/human-id.d.ts.map +1 -0
- package/dist/utils/worktree-manager.d.ts +3 -0
- package/dist/utils/worktree-manager.d.ts.map +1 -1
- package/dist/workflow-executor.d.ts.map +1 -1
- package/dist/workflow-registry.d.ts +1 -0
- package/dist/workflow-registry.d.ts.map +1 -1
- package/package.json +2 -2
- package/dist/sdk/chunk-BHZ4CKUS.mjs.map +0 -1
- package/dist/sdk/chunk-PVITVJ6J.mjs.map +0 -1
- package/dist/sdk/chunk-YLQ4UN62.mjs.map +0 -1
- package/dist/sdk/github-frontend-6Q4BISZX.mjs.map +0 -1
- /package/dist/sdk/{check-provider-registry-AQ3JETBG.mjs.map → check-provider-registry-3KI5RKXT.mjs.map} +0 -0
- /package/dist/sdk/{config-RQQPMLRD.mjs.map → check-provider-registry-IYILYY35.mjs.map} +0 -0
- /package/dist/sdk/{routing-DEY2AIXM.mjs.map → config-5AUYQFHE.mjs.map} +0 -0
- /package/dist/sdk/{host-P5NQICP7.mjs.map → host-4MT3EW2I.mjs.map} +0 -0
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
# Failure Routing (Retry/Goto/Remediate) — RFC
|
|
2
2
|
|
|
3
|
-
Status:
|
|
3
|
+
Status: **Implemented** (fully landed in engine, Phase 5 fanout/reduce included)
|
|
4
4
|
|
|
5
|
-
Last updated:
|
|
5
|
+
Last updated: 2026-01-28
|
|
6
6
|
|
|
7
7
|
Owner: Visor team
|
|
8
8
|
|
|
9
|
+
> **Note**: This RFC has been fully implemented. For user documentation, see
|
|
10
|
+
> [failure-routing.md](./failure-routing.md). The implementation includes all
|
|
11
|
+
> core features: `on_fail`, `on_success`, `on_finish`, retry with backoff,
|
|
12
|
+
> `goto`/`goto_js`, `run`/`run_js`, `goto_event`, fanout/reduce semantics, loop
|
|
13
|
+
> budgets, and forEach scope isolation.
|
|
14
|
+
|
|
9
15
|
## Objectives
|
|
10
16
|
|
|
11
17
|
- Enable a workflow step to handle failure by retrying, jumping back to a prior step, or running a remediation step, then continuing.
|
|
@@ -20,7 +26,9 @@ Owner: Visor team
|
|
|
20
26
|
|
|
21
27
|
## Config Sketch (MVP)
|
|
22
28
|
|
|
23
|
-
Proposed additions use Visor
|
|
29
|
+
Proposed additions use Visor's existing 2.0 style (type/exec/depends_on). New keys are `on_fail`, `on_success`, `on_finish`, and optional top‑level `routing` for defaults.
|
|
30
|
+
|
|
31
|
+
> **Implementation note**: The implementation also added `transitions` (declarative rule-based routing) and `goto_event` (event override for goto targets). See [failure-routing.md](./failure-routing.md) for full documentation.
|
|
24
32
|
|
|
25
33
|
```yaml
|
|
26
34
|
version: "2.0"
|
|
@@ -157,9 +165,10 @@ steps:
|
|
|
157
165
|
|
|
158
166
|
## CLI and UX
|
|
159
167
|
|
|
160
|
-
- Flags: `--on-fail-max-loops`, `--retry-max`, `--no-failure-routing` (to disable feature globally).
|
|
168
|
+
- **Future Flags** (not yet implemented): `--on-fail-max-loops`, `--retry-max`, `--no-failure-routing` (to disable feature globally).
|
|
161
169
|
- Run summary shows failure routes taken with timestamps and attempt counts.
|
|
162
170
|
- Debug: when `--debug` is set, include evaluated `*_js` results (with sensitive data redacted), sandbox timing, retry/backoff decisions, goto/run transitions, and per-scope loop counters.
|
|
171
|
+
- Telemetry: routing decisions are traced via OTel events (`visor.routing`) with attributes like `trigger`, `action`, `target`, `source`, `scope`, and `goto_event`.
|
|
163
172
|
|
|
164
173
|
## Tests and Demo
|
|
165
174
|
|
|
@@ -168,14 +177,24 @@ steps:
|
|
|
168
177
|
|
|
169
178
|
## Acceptance Criteria
|
|
170
179
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
-
|
|
174
|
-
-
|
|
175
|
-
-
|
|
176
|
-
-
|
|
177
|
-
-
|
|
178
|
-
-
|
|
180
|
+
All original acceptance criteria have been met:
|
|
181
|
+
|
|
182
|
+
- [x] **Goto**: Given a failing step with `goto: setup-env`, engine jumps to `setup-env`, proceeds, and re-runs the failed step.
|
|
183
|
+
- [x] **Remediation**: Given `run: [lint-fix]`, if remediation succeeds, the failed step re-runs once; if remediation fails, the run stops with a clear message.
|
|
184
|
+
- [x] **Retry**: Per-step retries respect backoff and caps; global `max_loops` prevents infinite ping-pong.
|
|
185
|
+
- [x] **Compatibility**: Configs without `on_fail` behave exactly as today.
|
|
186
|
+
- [x] **Observability**: Logs show ordered trace of retries and jumps; exit codes reflect final outcome.
|
|
187
|
+
- [x] **Dynamic routing**: `goto_js` and `run_js` work with pure, time-limited evaluation; precedence and merging behave as specified.
|
|
188
|
+
- [x] **forEach**: Each item runs with isolated counters; `*_js` receives `foreach` context and cannot jump across scopes.
|
|
189
|
+
- [x] **on_success goto**: After a step succeeds, `goto` (ancestor-only) can jump back to a prior step; with `max_loops` enforcement the run either converges or fails with a clear trace.
|
|
190
|
+
|
|
191
|
+
Additional features implemented beyond the original RFC:
|
|
192
|
+
|
|
193
|
+
- [x] **on_finish hook**: Runs after all forEach iterations and dependent checks complete — ideal for aggregation.
|
|
194
|
+
- [x] **goto_event**: Override the event trigger when performing a goto (e.g., simulate `pr_updated`).
|
|
195
|
+
- [x] **Declarative transitions**: Rule-based routing via `transitions: [{ when, to, goto_event }]` in on_fail/on_success/on_finish.
|
|
196
|
+
- [x] **Fanout/reduce**: Control whether routing targets run per-item (`fanout: map`) or as a single aggregation (`fanout: reduce`).
|
|
197
|
+
- [x] **Criticality-aware retry suppression**: High-criticality steps skip retries for logical failures (fail_if/guarantee).
|
|
179
198
|
|
|
180
199
|
## Open Questions
|
|
181
200
|
|
|
@@ -184,10 +203,16 @@ steps:
|
|
|
184
203
|
- Any preferred global default (e.g., retry once everywhere with linear 2s backoff)?
|
|
185
204
|
- Should we allow opt-in cross-scope targets via explicit qualifiers (e.g., `parent:setup-env`), guarded by additional loop caps?
|
|
186
205
|
|
|
187
|
-
## Next Steps
|
|
206
|
+
## Next Steps (Completed)
|
|
207
|
+
|
|
208
|
+
All primary implementation work is done:
|
|
209
|
+
|
|
210
|
+
1. ~~Audit current workflow engine & failure handling.~~ Done.
|
|
211
|
+
2. ~~Finalize config keys and schema validation messages.~~ Done — see `src/types/config.ts`.
|
|
212
|
+
3. ~~Implement engine changes with loop safeguards.~~ Done — see `src/state-machine/states/routing.ts`.
|
|
213
|
+
4. ~~Add tests and demos.~~ Done — see `tests/integration/routing-*.test.ts` and `examples/routing-*.yaml`.
|
|
214
|
+
5. ~~Extend docs and workshop slides.~~ Done — see [failure-routing.md](./failure-routing.md).
|
|
188
215
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
4. Add tests and the `lab-05-retry.yaml` demo.
|
|
193
|
-
5. Extend docs and workshop slides.
|
|
216
|
+
Remaining follow-ups:
|
|
217
|
+
- CLI flags (`--on-fail-max-loops`, `--retry-max`, `--no-failure-routing`) are planned but not yet implemented.
|
|
218
|
+
- Consider adding labeled checkpoints and opt-in cross-scope targets (see Open Questions).
|
|
@@ -77,7 +77,8 @@ steps:
|
|
|
77
77
|
on_success:
|
|
78
78
|
run: [notify]
|
|
79
79
|
goto_js: |
|
|
80
|
-
|
|
80
|
+
// Jump back only once using history length as proxy for attempt count
|
|
81
|
+
return outputs.history['build'].length === 1 ? 'unit' : null;
|
|
81
82
|
notify: { type: command, exec: "echo notify" }
|
|
82
83
|
```
|
|
83
84
|
|
|
@@ -117,10 +118,45 @@ Per-step actions:
|
|
|
117
118
|
- `retry`: `{ max, backoff: { mode: fixed|exponential, delay_ms } }`
|
|
118
119
|
- `run`: `[step-id, …]`
|
|
119
120
|
- `goto`: `step-id` (ancestor-only)
|
|
121
|
+
- `goto_event`: event to simulate during goto (e.g., `pr_updated`)
|
|
120
122
|
- `run_js`: JS returning `string[]`
|
|
121
123
|
- `goto_js`: JS returning `string | null`
|
|
124
|
+
- `transitions`: declarative transition rules (see below)
|
|
122
125
|
- `on_success`:
|
|
123
|
-
- `run`, `goto`, `run_js`, `goto_js` (same types and constraints as above)
|
|
126
|
+
- `run`, `goto`, `goto_event`, `run_js`, `goto_js`, `transitions` (same types and constraints as above)
|
|
127
|
+
- `on_finish` (forEach checks only):
|
|
128
|
+
- `run`, `goto`, `goto_event`, `run_js`, `goto_js`, `transitions` (same types and constraints as above)
|
|
129
|
+
|
|
130
|
+
### Declarative Transitions
|
|
131
|
+
|
|
132
|
+
The `transitions` field provides a declarative alternative to `goto_js`. It is an array of rules evaluated in order; the first matching rule wins:
|
|
133
|
+
|
|
134
|
+
```yaml
|
|
135
|
+
steps:
|
|
136
|
+
validate:
|
|
137
|
+
type: ai
|
|
138
|
+
on_success:
|
|
139
|
+
transitions:
|
|
140
|
+
- when: "outputs['validate'].score >= 90"
|
|
141
|
+
to: publish
|
|
142
|
+
- when: "outputs['validate'].score >= 70"
|
|
143
|
+
to: review
|
|
144
|
+
- when: "true" # default fallback
|
|
145
|
+
to: reject
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Each rule has:
|
|
149
|
+
- `when`: JavaScript expression evaluated in the same sandbox as `goto_js`
|
|
150
|
+
- `to`: target step ID, or `null` to explicitly skip goto
|
|
151
|
+
- `goto_event`: optional event override (same as `goto_event` above)
|
|
152
|
+
|
|
153
|
+
Helper functions available in `when` expressions:
|
|
154
|
+
- `any(arr, pred)` - returns true if any element matches predicate
|
|
155
|
+
- `all(arr, pred)` - returns true if all elements match predicate
|
|
156
|
+
- `none(arr, pred)` - returns true if no element matches predicate
|
|
157
|
+
- `count(arr, pred)` - returns count of elements matching predicate
|
|
158
|
+
|
|
159
|
+
When `transitions` is present, it takes precedence over `goto_js` and `goto`.
|
|
124
160
|
|
|
125
161
|
## Semantics
|
|
126
162
|
|
|
@@ -128,7 +164,7 @@ Per-step actions:
|
|
|
128
164
|
- Run: on failure (or success), run listed steps first; if successful, the failed step is re-attempted once (failure path).
|
|
129
165
|
- Goto (ancestor-only): jump back to a previously executed dependency, then continue forward. On success, Visor re-runs the current step once after the jump.
|
|
130
166
|
- Loop safety: `routing.max_loops` counts all routing transitions (runs, gotos, retries). Exceeding it aborts the current scope with a clear error. For a hard cap on repeated executions of the same step, see [Execution Limits](./limits.md).
|
|
131
|
-
- forEach: each item is isolated with its own loop/attempt counters; `*_js` receives
|
|
167
|
+
- forEach: each item is isolated with its own loop/attempt counters; `*_js` in on_finish context receives forEach metadata (see [Available Context in on_finish](#available-context-in-on_finish)).
|
|
132
168
|
|
|
133
169
|
### Fan‑out vs. Reduce (Phase 5)
|
|
134
170
|
|
|
@@ -214,7 +250,8 @@ steps:
|
|
|
214
250
|
on: [pr_opened, pr_updated]
|
|
215
251
|
on_success:
|
|
216
252
|
goto_js: |
|
|
217
|
-
|
|
253
|
+
// Jump back only once using history length as proxy for attempt count
|
|
254
|
+
return outputs.history['quality'].length === 1 ? 'overview' : null
|
|
218
255
|
goto_event: pr_updated
|
|
219
256
|
```
|
|
220
257
|
|
|
@@ -225,20 +262,26 @@ When to use goto_event vs. full re-run:
|
|
|
225
262
|
## Dynamic JS (safe, sync only)
|
|
226
263
|
|
|
227
264
|
- `goto_js` / `run_js` are evaluated in a sandbox with:
|
|
228
|
-
- Read-only context: `{ step,
|
|
265
|
+
- Read-only context: `{ step, outputs, outputs_history, outputs_raw, output, memory, event, forEach }`
|
|
229
266
|
- `outputs` contains current values, `outputs.history` contains arrays of all previous values (see [Output History](./output-history.md))
|
|
267
|
+
- `outputs_raw` provides aggregate/parent values (e.g., full array from forEach parent)
|
|
268
|
+
- `memory` provides read/write access to the memory store (get, set, has, getAll, increment, clear)
|
|
269
|
+
- `log()` function available for debugging (outputs with `Debug:` prefix)
|
|
230
270
|
- Pure sync execution; no IO, no async, no timers, no require/process.
|
|
231
271
|
- Time and size limits (short wall time; small code/output caps) — evaluation failures fall back to static routing.
|
|
232
272
|
|
|
273
|
+
Note: The `on_finish` context is richer and additionally includes `attempt`, `loop`, `pr`, `files`, and `env`.
|
|
274
|
+
|
|
233
275
|
Return types:
|
|
234
276
|
- `goto_js`: a `string` (step id) or `null`/`undefined` to skip.
|
|
235
277
|
- `run_js`: a `string[]` (may be empty). Duplicates are removed preserving order.
|
|
236
278
|
|
|
237
279
|
## Guardrails & Tips
|
|
238
280
|
|
|
239
|
-
- Keep `max_loops` small (5
|
|
281
|
+
- Keep `max_loops` small (5-10). Add retries sparingly and prefer remediation over blind loops.
|
|
240
282
|
- Restrict `goto` to ancestors to preserve dependency semantics and avoid hard-to-reason paths.
|
|
241
|
-
- For expensive remediations, put them behind `run_js` conditions keyed to `
|
|
283
|
+
- For expensive remediations, put them behind `run_js` conditions keyed to `output` or `outputs.history` values.
|
|
284
|
+
- Use `outputs.history['check-name'].length` as a proxy for attempt count in `goto_js`/`run_js`.
|
|
242
285
|
- In CI, you can override defaults with CLI flags (future): `--on-fail-max-loops`, `--retry-max`.
|
|
243
286
|
|
|
244
287
|
## on_finish Hook (forEach Aggregation & Routing)
|
|
@@ -289,30 +332,44 @@ The `on_finish` hooks have access to the complete execution context:
|
|
|
289
332
|
{
|
|
290
333
|
step: { id: 'extract-facts', tags: [...], group: '...' },
|
|
291
334
|
attempt: 1, // Current attempt number for this check
|
|
292
|
-
loop:
|
|
335
|
+
loop: 0, // Current loop number in routing
|
|
293
336
|
outputs: {
|
|
294
|
-
'extract-facts': [...],
|
|
295
|
-
'validate-fact': [...],
|
|
337
|
+
'extract-facts': [...], // Array of forEach items
|
|
338
|
+
'validate-fact': [...], // Array of ALL dependent results
|
|
339
|
+
history: { ... } // Alias for outputs_history
|
|
296
340
|
},
|
|
297
|
-
|
|
341
|
+
outputs_history: {
|
|
298
342
|
'extract-facts': [[...], ...], // Cross-loop history
|
|
299
343
|
'validate-fact': [[...], ...], // All results from all iterations
|
|
300
344
|
},
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
'
|
|
304
|
-
'validate-fact': [[...], ...],
|
|
345
|
+
outputs_raw: {
|
|
346
|
+
'extract-facts': [...], // Aggregate/parent values
|
|
347
|
+
'validate-fact': [...],
|
|
305
348
|
},
|
|
306
349
|
forEach: {
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
350
|
+
items: 3, // Number of forEach items
|
|
351
|
+
last_wave_size: 3, // Items in the last wave (when forEach parent)
|
|
352
|
+
last_items: [...], // The forEach items array (when forEach parent)
|
|
353
|
+
is_parent: true // Indicates this check is a forEach parent
|
|
354
|
+
},
|
|
355
|
+
memory: { // Memory access functions
|
|
356
|
+
get: (key, ns?) => ...,
|
|
357
|
+
set: (key, value, ns?) => ...,
|
|
358
|
+
has: (key, ns?) => ...,
|
|
359
|
+
getAll: (ns?) => ...,
|
|
360
|
+
increment: (key, amount?, ns?) => ...,
|
|
361
|
+
clear: (ns?) => ...
|
|
362
|
+
},
|
|
363
|
+
pr: { // PR metadata
|
|
364
|
+
number: 123,
|
|
365
|
+
title: '...',
|
|
366
|
+
author: '...',
|
|
367
|
+
branch: '...',
|
|
368
|
+
base: '...'
|
|
311
369
|
},
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
env // Environment variables
|
|
370
|
+
files: [...], // Changed files
|
|
371
|
+
env: { ... }, // Environment variables (filtered for safety)
|
|
372
|
+
event: { name: '...' } // Event that triggered execution
|
|
316
373
|
}
|
|
317
374
|
```
|
|
318
375
|
|