@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
|
@@ -141,14 +141,39 @@ Custom tools are designed to be fully compatible with the Model Context Protocol
|
|
|
141
141
|
|
|
142
142
|
## Using Custom Tools
|
|
143
143
|
|
|
144
|
-
|
|
144
|
+
### In AI Steps
|
|
145
|
+
|
|
146
|
+
Use `ai_custom_tools` to expose custom tools to AI providers via an ephemeral MCP server. See [AI Custom Tools](./ai-custom-tools.md) for complete documentation.
|
|
147
|
+
|
|
148
|
+
```yaml
|
|
149
|
+
steps:
|
|
150
|
+
ai-review:
|
|
151
|
+
type: ai
|
|
152
|
+
prompt: |
|
|
153
|
+
Use the available tools to analyze the code for issues.
|
|
154
|
+
ai_custom_tools:
|
|
155
|
+
- grep-pattern
|
|
156
|
+
- file-stats
|
|
157
|
+
ai:
|
|
158
|
+
provider: anthropic
|
|
159
|
+
model: claude-3-5-sonnet-20241022
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### In MCP Steps
|
|
163
|
+
|
|
164
|
+
Custom tools can also be used directly in MCP steps by setting `transport: custom`. The MCP provider supports four transport types:
|
|
165
|
+
|
|
166
|
+
- `stdio` - Spawn an MCP server as a subprocess (default)
|
|
167
|
+
- `sse` - Connect to an MCP server via Server-Sent Events (legacy)
|
|
168
|
+
- `http` - Connect via Streamable HTTP transport
|
|
169
|
+
- `custom` - Execute YAML-defined custom tools directly
|
|
145
170
|
|
|
146
171
|
```yaml
|
|
147
172
|
steps:
|
|
148
173
|
my-check:
|
|
149
174
|
type: mcp
|
|
150
|
-
transport: custom # Use custom transport
|
|
151
|
-
method: my-tool # Tool name
|
|
175
|
+
transport: custom # Use custom transport for YAML-defined tools
|
|
176
|
+
method: my-tool # Tool name (must be defined in tools: section)
|
|
152
177
|
methodArgs: # Tool arguments
|
|
153
178
|
param1: "value1"
|
|
154
179
|
param2: 42
|
|
@@ -160,17 +185,23 @@ Tools have access to a rich template context through Liquid templates:
|
|
|
160
185
|
|
|
161
186
|
### In `exec` and `stdin`:
|
|
162
187
|
- `{{ args }}` - The arguments passed to the tool
|
|
163
|
-
- `{{
|
|
188
|
+
- `{{ input }}` - Alias for `args` (same object)
|
|
189
|
+
- `{{ pr }}` - Pull request information:
|
|
190
|
+
- `{{ pr.number }}` - PR number
|
|
191
|
+
- `{{ pr.title }}` - PR title
|
|
192
|
+
- `{{ pr.author }}` - PR author
|
|
193
|
+
- `{{ pr.branch }}` - Head branch name
|
|
194
|
+
- `{{ pr.base }}` - Base branch name
|
|
164
195
|
- `{{ files }}` - List of files in the PR
|
|
165
196
|
- `{{ outputs }}` - Outputs from previous checks
|
|
166
197
|
- `{{ env }}` - Environment variables
|
|
167
198
|
|
|
168
199
|
### In `transform` and `transform_js`:
|
|
169
200
|
- All of the above, plus:
|
|
170
|
-
- `{{ output }}` - The raw command output
|
|
171
|
-
- `{{ stdout }}` - Standard output
|
|
172
|
-
- `{{ stderr }}` - Standard error
|
|
173
|
-
- `{{ exitCode }}` - Command exit code
|
|
201
|
+
- `{{ output }}` - The raw command output (or parsed JSON if `parseJson: true`)
|
|
202
|
+
- `{{ stdout }}` - Standard output (raw string)
|
|
203
|
+
- `{{ stderr }}` - Standard error (raw string)
|
|
204
|
+
- `{{ exitCode }}` - Command exit code (number)
|
|
174
205
|
|
|
175
206
|
## Examples
|
|
176
207
|
|
|
@@ -1,23 +1,37 @@
|
|
|
1
|
-
Dashboards for Visor Telemetry
|
|
2
|
-
==============================
|
|
1
|
+
# Dashboards for Visor Telemetry
|
|
3
2
|
|
|
4
3
|
This folder contains example Grafana dashboards to visualize Visor traces and metrics exported via OpenTelemetry (Tempo + Prometheus).
|
|
5
4
|
|
|
6
|
-
What
|
|
7
|
-
|
|
8
|
-
- grafana-visor-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
5
|
+
## What's Included
|
|
6
|
+
|
|
7
|
+
- **grafana-visor-overview.json** - Run/Check overview dashboard with:
|
|
8
|
+
- Check duration histogram (95th percentile)
|
|
9
|
+
- Issues by severity rate panel
|
|
10
|
+
- **grafana-visor-diagrams.json** - Diagram telemetry dashboard with:
|
|
11
|
+
- Diagram blocks by origin (content vs issue)
|
|
12
|
+
|
|
13
|
+
## Setup
|
|
14
|
+
|
|
15
|
+
1. Deploy Grafana + Tempo + Prometheus (or Grafana Cloud).
|
|
16
|
+
2. Configure your OTel Collector to receive OTLP traces/metrics and forward to Tempo/Prometheus.
|
|
17
|
+
3. Enable telemetry in Visor CI:
|
|
18
|
+
```bash
|
|
19
|
+
export VISOR_TELEMETRY_ENABLED=true
|
|
20
|
+
export VISOR_TELEMETRY_SINK=otlp
|
|
21
|
+
export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=https://collector.example.com/v1/traces
|
|
22
|
+
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer <token>"
|
|
23
|
+
```
|
|
24
|
+
4. Import the JSON dashboards into Grafana.
|
|
25
|
+
5. Update the data source UIDs in each dashboard to match your Tempo and Prometheus data sources (replace `PROM_DS` with your Prometheus data source UID).
|
|
26
|
+
|
|
27
|
+
## Notes
|
|
28
|
+
|
|
29
|
+
- Spans appear in Tempo's Explore/Trace view (service.name=visor).
|
|
30
|
+
- Metrics are emitted when the OTLP metrics exporter is configured.
|
|
31
|
+
- The dashboards use placeholder data source UIDs (`PROM_DS`) that need to be updated after import.
|
|
32
|
+
|
|
33
|
+
## Related Documentation
|
|
34
|
+
|
|
35
|
+
- [Telemetry Setup Guide](../telemetry-setup.md) - Complete setup instructions for enabling telemetry
|
|
36
|
+
- [Telemetry RFC](../telemetry-tracing-rfc.md) - Design rationale and architecture details
|
|
23
37
|
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
# Debug Visualizer Implementation Progress
|
|
2
2
|
|
|
3
|
+
> **Note**: This is a historical progress tracking document from the debug visualizer RFC implementation.
|
|
4
|
+
> The implementation is largely complete (Milestones 1-5). See [debug-visualizer.md](debug-visualizer.md) for current usage documentation.
|
|
5
|
+
|
|
3
6
|
**Last Updated**: 2025-10-17
|
|
4
|
-
**Status**:
|
|
7
|
+
**Status**: 5 of 6 Milestones Complete (83%)
|
|
5
8
|
|
|
6
9
|
---
|
|
7
10
|
|
|
@@ -111,7 +114,7 @@ From `tests/e2e/state-capture-e2e.test.ts`:
|
|
|
111
114
|
- 🔄 At least one `state.snapshot` event is present (pending snapshot integration)
|
|
112
115
|
- ✅ All tests pass
|
|
113
116
|
|
|
114
|
-
**Full Details**:
|
|
117
|
+
**Full Details**: See milestone details below.
|
|
115
118
|
|
|
116
119
|
---
|
|
117
120
|
|
|
@@ -158,7 +161,7 @@ From `tests/e2e/state-capture-e2e.test.ts`:
|
|
|
158
161
|
- ✅ Timeline events are in chronological order
|
|
159
162
|
- ✅ All tests pass (26/26 = 100%)
|
|
160
163
|
|
|
161
|
-
**Full Details**:
|
|
164
|
+
**Full Details**: See milestone details below.
|
|
162
165
|
|
|
163
166
|
---
|
|
164
167
|
|
|
@@ -205,11 +208,10 @@ From `tests/e2e/state-capture-e2e.test.ts`:
|
|
|
205
208
|
- **Output**: Check results and outputs
|
|
206
209
|
- **Events**: All span events with timestamps and attributes
|
|
207
210
|
|
|
208
|
-
|
|
209
|
-
-
|
|
210
|
-
-
|
|
211
|
-
-
|
|
212
|
-
- Expected behavior documentation
|
|
211
|
+
**Testing with fixtures** (`tests/fixtures/traces/`)
|
|
212
|
+
- `sample-trace.ndjson` - Complete execution trace
|
|
213
|
+
- `error-trace.ndjson` - Error scenario trace
|
|
214
|
+
- `empty-trace.ndjson` - Empty file for error handling
|
|
213
215
|
|
|
214
216
|
✅ **Embedded trace reader**
|
|
215
217
|
- Inline implementation of all trace-reader functions
|
|
@@ -237,7 +239,7 @@ From `tests/e2e/state-capture-e2e.test.ts`:
|
|
|
237
239
|
- ✅ Loading spinner
|
|
238
240
|
- ✅ Responsive design
|
|
239
241
|
|
|
240
|
-
**Full Details**:
|
|
242
|
+
**Full Details**: See milestone details below.
|
|
241
243
|
|
|
242
244
|
---
|
|
243
245
|
|
|
@@ -431,20 +433,19 @@ Build completed successfully:
|
|
|
431
433
|
### Next Steps
|
|
432
434
|
|
|
433
435
|
Ready to proceed to Milestone 5 (Time-Travel Debugging) or Milestone 6 (CLI Viewer).
|
|
434
|
-
**Full Details**: [MILESTONE4-INTEGRATION-GUIDE.md](../MILESTONE4-INTEGRATION-GUIDE.md)
|
|
435
436
|
|
|
436
437
|
---
|
|
437
438
|
|
|
438
439
|
## Overall Progress Summary
|
|
439
440
|
|
|
440
|
-
**Milestones Completed**:
|
|
441
|
+
**Milestones Completed**: 5 of 6 (83%)
|
|
441
442
|
|
|
442
443
|
```
|
|
443
444
|
Milestone 1: State Capture Foundation ████████████████████ 100% ✅
|
|
444
445
|
Milestone 2: Trace File Reader ████████████████████ 100% ✅
|
|
445
446
|
Milestone 3: Static UI Viewer ████████████████████ 100% ✅
|
|
446
|
-
Milestone 4: Live Streaming Server ████████████████████ 100% ✅
|
|
447
|
-
Milestone 5: Time-Travel Debugging
|
|
447
|
+
Milestone 4: Live Streaming Server ████████████████████ 100% ✅
|
|
448
|
+
Milestone 5: Time-Travel Debugging ████████████████████ 100% ✅
|
|
448
449
|
Milestone 6: Production Ready ░░░░░░░░░░░░░░░░░░░░ 0% 📋
|
|
449
450
|
```
|
|
450
451
|
|
|
@@ -399,7 +399,6 @@ cat output/traces/run-*.ndjson | jq '.attributes | select(."visor.check.input.co
|
|
|
399
399
|
- ✅ `tests/unit/telemetry/state-capture.test.ts` (246 lines)
|
|
400
400
|
- ✅ `tests/e2e/state-capture-e2e.test.ts` (195 lines)
|
|
401
401
|
- ✅ Integration in 3 providers + execution engine
|
|
402
|
-
- ✅ [MILESTONE1-COMPLETE.md](../MILESTONE1-COMPLETE.md) - Full summary
|
|
403
402
|
|
|
404
403
|
---
|
|
405
404
|
|
|
@@ -562,8 +561,6 @@ open output/traces/index.html
|
|
|
562
561
|
- ✅ `src/telemetry/opentelemetry.ts` (updated) - Debug exporter support
|
|
563
562
|
- ✅ `src/debug-visualizer/ui/index.html` (updated) - WebSocket client
|
|
564
563
|
- ✅ `package.json` (updated) - Dependencies and build script
|
|
565
|
-
- ✅ `MILESTONE4-INTEGRATION-GUIDE.md` - Integration documentation
|
|
566
|
-
- ✅ `MILESTONE4-COMPLETE.md` - Completion summary
|
|
567
564
|
|
|
568
565
|
**Dependencies Installed**:
|
|
569
566
|
- ✅ ws@^8.18.3
|
|
@@ -602,14 +599,18 @@ open "output/traces/index.html?trace=run-2025-10-17.ndjson"
|
|
|
602
599
|
# 7. Arrow keys step forward/backward
|
|
603
600
|
```
|
|
604
601
|
|
|
605
|
-
**Success Criteria**:
|
|
606
|
-
- [
|
|
607
|
-
- [
|
|
608
|
-
- [
|
|
609
|
-
- [
|
|
610
|
-
- [
|
|
611
|
-
- [
|
|
612
|
-
- [
|
|
602
|
+
**Success Criteria**: ✅ ALL MET
|
|
603
|
+
- [x] Timeline scrubber updates graph to show state at selected time
|
|
604
|
+
- [x] Play button animates execution from start to finish
|
|
605
|
+
- [x] Can pause at any point and inspect state
|
|
606
|
+
- [x] Diff view highlights changes between timepoints
|
|
607
|
+
- [x] State snapshot markers are clickable
|
|
608
|
+
- [x] Keyboard shortcuts work correctly
|
|
609
|
+
- [x] Performance: smooth scrubbing with 1000+ spans
|
|
610
|
+
|
|
611
|
+
**Deliverables**:
|
|
612
|
+
- ✅ `src/debug-visualizer/ui/index.html` (updated) - Timeline component, styles, and JavaScript engine
|
|
613
|
+
- ✅ `tests/unit/debug-visualizer/time-travel.test.ts` - 17 comprehensive unit tests
|
|
613
614
|
|
|
614
615
|
---
|
|
615
616
|
|
|
@@ -662,10 +663,10 @@ The debug visualizer is complete when:
|
|
|
662
663
|
2. [x] **Data Layer**: Can parse traces and rebuild execution tree ✅ M2 DONE
|
|
663
664
|
3. [x] **Visualization**: Can see execution graph in browser ✅ M3 DONE
|
|
664
665
|
4. [x] **Real-time**: Can stream live execution ✅ M4 DONE
|
|
665
|
-
5. [
|
|
666
|
+
5. [x] **Time-Travel**: Can scrub timeline and see historical state ✅ M5 DONE
|
|
666
667
|
6. [ ] **Production**: Polished UI with docs and tests (M6)
|
|
667
668
|
|
|
668
|
-
### Current Status: 🟢 Milestone
|
|
669
|
+
### Current Status: 🟢 Milestone 5 of 6 Complete (83%)
|
|
669
670
|
|
|
670
671
|
## Open Questions
|
|
671
672
|
|
|
@@ -5,9 +5,10 @@ The Debug Visualizer is a lightweight HTTP server that streams OpenTelemetry spa
|
|
|
5
5
|
## Quick Start
|
|
6
6
|
|
|
7
7
|
- Start the CLI with the debug server:
|
|
8
|
-
- `
|
|
8
|
+
- `visor --config <path/to/.visor.yaml> --output json --debug-server --debug-port 3456`
|
|
9
|
+
- Or using the development build: `node dist/cli-main.js --config <path/to/.visor.yaml> --output json --debug-server --debug-port 3456`
|
|
9
10
|
- The server starts at `http://localhost:3456`. In headless CI, set `VISOR_NOBROWSER=true` to skip auto‑open.
|
|
10
|
-
- Click
|
|
11
|
+
- Click "Start Execution" in the UI or POST `/api/start` (see below) to begin.
|
|
11
12
|
|
|
12
13
|
## Control Endpoints
|
|
13
14
|
|
|
@@ -56,6 +57,23 @@ The Debug Visualizer is a lightweight HTTP server that streams OpenTelemetry spa
|
|
|
56
57
|
}
|
|
57
58
|
```
|
|
58
59
|
|
|
60
|
+
### Config shape (`GET /api/config`)
|
|
61
|
+
```json
|
|
62
|
+
{
|
|
63
|
+
"config": { /* loaded configuration object */ },
|
|
64
|
+
"timestamp": "2025-01-01T00:00:00.000Z"
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Results shape (`GET /api/results`)
|
|
69
|
+
```json
|
|
70
|
+
{
|
|
71
|
+
"results": { /* check results by check name */ },
|
|
72
|
+
"timestamp": "2025-01-01T00:00:00.000Z",
|
|
73
|
+
"executionState": "stopped"
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
59
77
|
## Pause/Stop Semantics
|
|
60
78
|
|
|
61
79
|
The engine checks a “pause gate” at key scheduling points:
|
|
@@ -81,14 +99,14 @@ Effects:
|
|
|
81
99
|
## CLI Examples
|
|
82
100
|
|
|
83
101
|
- Start server headless on port 40000 and begin automatically from script:
|
|
84
|
-
- `VISOR_NOBROWSER=true
|
|
102
|
+
- `VISOR_NOBROWSER=true visor --config .visor.yaml --output json --debug-server --debug-port 40000`
|
|
85
103
|
- Then: `curl -sSf -X POST http://localhost:40000/api/start`.
|
|
86
104
|
- Pause/Resume/Stop from a terminal:
|
|
87
105
|
- `curl -sSf -X POST http://localhost:40000/api/pause`
|
|
88
106
|
- `curl -sSf -X POST http://localhost:40000/api/resume`
|
|
89
107
|
- `curl -sSf -X POST http://localhost:40000/api/stop`
|
|
90
108
|
- Inspect spans/status:
|
|
91
|
-
- `curl -sSf http://localhost:40000/api/status | jq`
|
|
109
|
+
- `curl -sSf http://localhost:40000/api/status | jq`
|
|
92
110
|
- `curl -sSf http://localhost:40000/api/spans | jq '.total'`
|
|
93
111
|
|
|
94
112
|
## Spans & State Capture
|
|
@@ -109,6 +127,13 @@ You can parse NDJSON via the built‑in trace reader (`src/debug-visualizer/trac
|
|
|
109
127
|
|
|
110
128
|
## Troubleshooting
|
|
111
129
|
|
|
112
|
-
- Server started but CLI doesn
|
|
130
|
+
- Server started but CLI doesn't proceed: send `POST /api/start` or set a start timeout with `VISOR_DEBUG_START_TIMEOUT_MS`.
|
|
113
131
|
- No spans in file: confirm `VISOR_TELEMETRY_ENABLED=true` and `VISOR_TELEMETRY_SINK=file`. Check `VISOR_TRACE_DIR` exists.
|
|
114
132
|
- Duplicate OpenTelemetry context warning: benign; initialization is guarded, but concurrent runs can still log a warning.
|
|
133
|
+
|
|
134
|
+
## Related Documentation
|
|
135
|
+
|
|
136
|
+
- [Debugging Guide](./debugging.md) — Comprehensive debugging techniques and tools
|
|
137
|
+
- [Telemetry Setup](./telemetry-setup.md) — Configuring OpenTelemetry tracing and metrics
|
|
138
|
+
- [Engine Pause/Resume RFC](./engine-pause-resume-rfc.md) — Design rationale for pause/resume semantics
|
|
139
|
+
- [Debug Visualizer RFC](./debug-visualizer-rfc.md) — Original design specification
|
package/dist/docs/debugging.md
CHANGED
|
@@ -10,6 +10,8 @@ This guide provides comprehensive debugging techniques and tools to help trouble
|
|
|
10
10
|
- [Common Debugging Patterns](#common-debugging-patterns)
|
|
11
11
|
- [Author Permission Functions](#author-permission-functions)
|
|
12
12
|
- [Troubleshooting Tips](#troubleshooting-tips)
|
|
13
|
+
- [Tracing with OpenTelemetry](#tracing-with-opentelemetry)
|
|
14
|
+
- [Debug Visualizer](#debug-visualizer)
|
|
13
15
|
|
|
14
16
|
## Debug Mode
|
|
15
17
|
|
|
@@ -423,19 +425,24 @@ steps:
|
|
|
423
425
|
Set these environment variables for additional debug output:
|
|
424
426
|
|
|
425
427
|
```bash
|
|
426
|
-
#
|
|
428
|
+
# Enable verbose debug output (used in diff processing and other internals)
|
|
427
429
|
export DEBUG=1
|
|
430
|
+
# or
|
|
431
|
+
export VERBOSE=1
|
|
428
432
|
|
|
429
|
-
#
|
|
430
|
-
export
|
|
433
|
+
# Enable telemetry and tracing
|
|
434
|
+
export VISOR_TELEMETRY_ENABLED=true
|
|
435
|
+
export VISOR_TELEMETRY_SINK=file # or otlp, console
|
|
431
436
|
|
|
432
|
-
#
|
|
433
|
-
export
|
|
437
|
+
# Set trace output directory
|
|
438
|
+
export VISOR_TRACE_DIR=output/traces
|
|
434
439
|
|
|
435
|
-
#
|
|
436
|
-
export
|
|
440
|
+
# For headless/CI environments (skip auto-opening browser)
|
|
441
|
+
export VISOR_NOBROWSER=true
|
|
437
442
|
```
|
|
438
443
|
|
|
444
|
+
See [Telemetry Setup](./telemetry-setup.md) for detailed configuration of tracing and metrics.
|
|
445
|
+
|
|
439
446
|
## Common Issues and Solutions
|
|
440
447
|
|
|
441
448
|
### Issue: "outputs is undefined"
|
|
@@ -628,9 +635,67 @@ steps:
|
|
|
628
635
|
outputs["security-scan"].criticalIssues === 0
|
|
629
636
|
```
|
|
630
637
|
|
|
638
|
+
## Tracing with OpenTelemetry
|
|
639
|
+
|
|
640
|
+
Visor supports OpenTelemetry tracing for deep execution visibility. Enable tracing to see:
|
|
641
|
+
|
|
642
|
+
- **Root span**: `visor.run` - one per CLI/Slack execution
|
|
643
|
+
- **State spans**: `engine.state.*` with `wave`, `wave_kind`, `session_id` attributes
|
|
644
|
+
- **Check spans**: `visor.check.<checkId>` with `visor.check.id`, `visor.check.type`, `visor.foreach.index` (for map fanout)
|
|
645
|
+
- **Routing decisions**: `visor.routing` events with `trigger`, `action`, `source`, `target`, `scope`, `goto_event`
|
|
646
|
+
- **Wave visibility**: `engine.state.level_dispatch` includes `level_size` and `level_checks_preview`
|
|
647
|
+
|
|
648
|
+
### Quick Start with Jaeger
|
|
649
|
+
|
|
650
|
+
```bash
|
|
651
|
+
# Start Jaeger locally
|
|
652
|
+
docker run -d --name jaeger \
|
|
653
|
+
-p 16686:16686 \
|
|
654
|
+
-p 4318:4318 \
|
|
655
|
+
jaegertracing/all-in-one:latest
|
|
656
|
+
|
|
657
|
+
# Run Visor with tracing enabled
|
|
658
|
+
VISOR_TELEMETRY_ENABLED=true \
|
|
659
|
+
VISOR_TELEMETRY_SINK=otlp \
|
|
660
|
+
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://localhost:4318/v1/traces \
|
|
661
|
+
visor --config .visor.yaml
|
|
662
|
+
|
|
663
|
+
# View traces at http://localhost:16686
|
|
664
|
+
```
|
|
665
|
+
|
|
666
|
+
For complete tracing setup and configuration, see [Telemetry Setup](./telemetry-setup.md).
|
|
667
|
+
|
|
668
|
+
## Debug Visualizer
|
|
669
|
+
|
|
670
|
+
Visor includes a built-in debug visualizer - a lightweight HTTP server that streams OpenTelemetry spans during execution and provides control endpoints for pause/resume/stop.
|
|
671
|
+
|
|
672
|
+
### Starting the Debug Visualizer
|
|
673
|
+
|
|
674
|
+
```bash
|
|
675
|
+
# Start with debug server
|
|
676
|
+
visor --config .visor.yaml --debug-server --debug-port 3456
|
|
677
|
+
|
|
678
|
+
# For CI/headless environments
|
|
679
|
+
VISOR_NOBROWSER=true visor --config .visor.yaml --debug-server --debug-port 3456
|
|
680
|
+
```
|
|
681
|
+
|
|
682
|
+
### Control Endpoints
|
|
683
|
+
|
|
684
|
+
- `GET /api/status` - Execution state and readiness
|
|
685
|
+
- `GET /api/spans` - Current in-memory spans (live view)
|
|
686
|
+
- `POST /api/start` - Begin execution
|
|
687
|
+
- `POST /api/pause` - Pause scheduling (in-flight work continues)
|
|
688
|
+
- `POST /api/resume` - Resume scheduling
|
|
689
|
+
- `POST /api/stop` - Stop scheduling new work
|
|
690
|
+
- `POST /api/reset` - Clear spans and return to idle
|
|
691
|
+
|
|
692
|
+
For complete debug visualizer documentation, see [Debug Visualizer](./debug-visualizer.md).
|
|
693
|
+
|
|
631
694
|
## Further Reading
|
|
632
695
|
|
|
633
696
|
- [Liquid Templates Guide](./liquid-templates.md) - Template syntax and variables
|
|
634
697
|
- [Command Provider Documentation](./command-provider.md) - Command execution and transforms
|
|
635
698
|
- [Configuration Reference](./configuration.md) - Full configuration options
|
|
636
|
-
- [
|
|
699
|
+
- [Telemetry Setup](./telemetry-setup.md) - OpenTelemetry tracing and metrics
|
|
700
|
+
- [Debug Visualizer](./debug-visualizer.md) - Live execution visualization
|
|
701
|
+
- [Output History](./output-history.md) - Tracking outputs across loop iterations
|
|
@@ -1,28 +1,32 @@
|
|
|
1
1
|
# Default Output Schema and Timestamps
|
|
2
2
|
|
|
3
|
-
Visor
|
|
3
|
+
Visor adds timestamps to check outputs to make history handling predictable.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
- The provider's output shape is respected.
|
|
7
|
-
- If the final output is an Object (map), Visor injects a `ts` field (milliseconds since epoch) if it is missing.
|
|
8
|
-
- If the final output is a primitive or an array, it is passed through unchanged (no wrapping, no `ts`).
|
|
5
|
+
## Timestamp Injection
|
|
9
6
|
|
|
10
|
-
|
|
11
|
-
-
|
|
12
|
-
- If the
|
|
13
|
-
- If it returned an Object, Visor injects `ts` if it is missing.
|
|
14
|
-
- If it returned an array, it is passed through unchanged.
|
|
7
|
+
When a check completes successfully:
|
|
8
|
+
- If the output is a plain **Object** (not an array, not null), Visor injects a `ts` field (milliseconds since epoch) if it is missing.
|
|
9
|
+
- If the output is a **primitive** (string, number, boolean), **array**, or **null**, it is passed through unchanged (no wrapping, no `ts`).
|
|
15
10
|
|
|
16
|
-
This
|
|
11
|
+
This injection happens after the provider returns and before outputs are recorded into `outputs` and `outputs_history`.
|
|
17
12
|
|
|
18
|
-
|
|
19
|
-
- Prompts and templates can reliably access `.text` and `.ts` for no‑schema checks (e.g., human‑input), and can still trust custom shapes for schema’d checks.
|
|
20
|
-
- `ts` allows you to sort/merge histories across steps without bespoke engines or roles.
|
|
13
|
+
## Provider-Specific Defaults
|
|
21
14
|
|
|
22
|
-
|
|
23
|
-
-
|
|
24
|
-
-
|
|
25
|
-
- Arrays are passed through untouched; if you need timestamps per item, include them in your own schema.
|
|
15
|
+
Some providers return structured output by default:
|
|
16
|
+
- **human-input**: Returns `{ text: string, ts: number }` directly from the provider (not via central normalization).
|
|
17
|
+
- **Other providers**: Return whatever their implementation produces; Visor only adds `ts` to objects.
|
|
26
18
|
|
|
27
|
-
|
|
28
|
-
|
|
19
|
+
## Why Timestamps Exist
|
|
20
|
+
|
|
21
|
+
- `ts` allows you to sort/merge histories across steps without custom logic.
|
|
22
|
+
- Providers that need structured output (like human-input) implement it directly.
|
|
23
|
+
|
|
24
|
+
## Practical Tips
|
|
25
|
+
|
|
26
|
+
- Human input always returns `{ text, ts }`. In Liquid, access via `outputs['my-check'].text`.
|
|
27
|
+
- For AI checks with custom schemas, add `ts` to your schema if you want it persisted by validators; otherwise Visor adds it at runtime (not validated).
|
|
28
|
+
- Arrays are passed through untouched; if you need timestamps per item, include them in your schema.
|
|
29
|
+
|
|
30
|
+
## Related
|
|
31
|
+
|
|
32
|
+
- See [Human Input Provider](./human-input-provider.md) for the default output shape of human input.
|
|
@@ -117,7 +117,7 @@ steps:
|
|
|
117
117
|
```
|
|
118
118
|
|
|
119
119
|
```yaml
|
|
120
|
-
|
|
120
|
+
steps:
|
|
121
121
|
parse-issue: { type: noop }
|
|
122
122
|
parse-comment: { type: noop }
|
|
123
123
|
triage: { type: noop, depends_on: ["parse-issue|parse-comment"] }
|
|
@@ -132,6 +132,56 @@ Rules:
|
|
|
132
132
|
|
|
133
133
|
Tip: When targeting a leaf in ad‑hoc runs (e.g., `visor --check final`), include one member of each pipe group explicitly (e.g., `--check a --check final`) to make intent unambiguous. In normal runs Visor computes the plan automatically from your config.
|
|
134
134
|
|
|
135
|
+
### AI Session Reuse
|
|
136
|
+
|
|
137
|
+
For AI checks that depend on other AI checks, you can reuse the parent's conversation session to maintain context:
|
|
138
|
+
|
|
139
|
+
```yaml
|
|
140
|
+
steps:
|
|
141
|
+
initial-analysis:
|
|
142
|
+
type: ai
|
|
143
|
+
prompt: "Analyze this code for issues..."
|
|
144
|
+
|
|
145
|
+
follow-up:
|
|
146
|
+
type: ai
|
|
147
|
+
depends_on: [initial-analysis]
|
|
148
|
+
reuse_ai_session: true # Reuses session from first dependency
|
|
149
|
+
prompt: "Based on your analysis, suggest fixes..."
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Options:
|
|
153
|
+
- `reuse_ai_session: true` - Reuse session from first dependency
|
|
154
|
+
- `reuse_ai_session: "step-name"` - Reuse session from specific step
|
|
155
|
+
- `session_mode: 'clone'` - Copy conversation history (default)
|
|
156
|
+
- `session_mode: 'append'` - Share conversation history (modifications visible to both)
|
|
157
|
+
|
|
158
|
+
When using ANY-OF dependencies (`depends_on: ["a|b"]`), the session is taken from whichever dependency completes first.
|
|
159
|
+
|
|
160
|
+
### Fanout Control
|
|
161
|
+
|
|
162
|
+
When a step is triggered via routing (`on_success.run`, `on_fail.run`) from a forEach scope, you can control how it schedules:
|
|
163
|
+
|
|
164
|
+
```yaml
|
|
165
|
+
steps:
|
|
166
|
+
process-items:
|
|
167
|
+
type: command
|
|
168
|
+
forEach: true
|
|
169
|
+
exec: echo '["a","b","c"]'
|
|
170
|
+
|
|
171
|
+
validate-item:
|
|
172
|
+
depends_on: [process-items]
|
|
173
|
+
fanout: map # Run once per forEach item (fan-out)
|
|
174
|
+
|
|
175
|
+
aggregate-results:
|
|
176
|
+
depends_on: [process-items]
|
|
177
|
+
fanout: reduce # Run once at parent scope (aggregation)
|
|
178
|
+
# Alias: reduce: true
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
- `fanout: 'map'` - Schedule once per forEach item (fan-out behavior)
|
|
182
|
+
- `fanout: 'reduce'` - Schedule a single run at parent scope (aggregation)
|
|
183
|
+
- `reduce: true` - Alias for `fanout: 'reduce'`
|
|
184
|
+
|
|
135
185
|
### Error Handling
|
|
136
186
|
|
|
137
187
|
- Cycle detection and missing dependency validation
|
|
@@ -145,7 +195,7 @@ When a check has `forEach: true`, it outputs an array and all its dependent chec
|
|
|
145
195
|
### Basic Flow
|
|
146
196
|
|
|
147
197
|
```yaml
|
|
148
|
-
|
|
198
|
+
steps:
|
|
149
199
|
extract-items:
|
|
150
200
|
type: ai
|
|
151
201
|
forEach: true
|
|
@@ -167,7 +217,7 @@ checks:
|
|
|
167
217
|
The `on_finish` hook runs **once** after all dependent checks complete all their iterations, making it perfect for aggregating results and making routing decisions:
|
|
168
218
|
|
|
169
219
|
```yaml
|
|
170
|
-
|
|
220
|
+
steps:
|
|
171
221
|
extract-facts:
|
|
172
222
|
type: ai
|
|
173
223
|
forEach: true
|
|
@@ -214,33 +264,37 @@ checks:
|
|
|
214
264
|
|
|
215
265
|
### Accessing forEach Results
|
|
216
266
|
|
|
217
|
-
Inside `on_finish` hooks, you have access to all iteration results
|
|
267
|
+
Inside `on_finish` hooks, you have access to all iteration results. The context provides these variables:
|
|
218
268
|
|
|
219
269
|
```javascript
|
|
220
270
|
// In on_finish.goto_js or on_finish.run_js
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
271
|
+
// Available variables:
|
|
272
|
+
outputs['extract-facts'] // The forEach array (latest value)
|
|
273
|
+
outputs['validate-fact'] // Latest result from validate-fact
|
|
274
|
+
outputs.history['validate-fact'] // ALL results from ALL iterations (array)
|
|
275
|
+
outputs_history['validate-fact'] // Alias for outputs.history
|
|
276
|
+
outputs_raw['extract-facts'] // Aggregate value (full array)
|
|
277
|
+
|
|
278
|
+
// forEach metadata
|
|
279
|
+
forEach.total // Total forEach items
|
|
280
|
+
forEach.successful // Number of successful iterations
|
|
281
|
+
forEach.failed // Number of failed iterations
|
|
282
|
+
forEach.items // The forEach items array
|
|
283
|
+
|
|
284
|
+
// Memory access
|
|
285
|
+
memory.get('key', 'namespace')
|
|
286
|
+
memory.set('key', value, 'namespace')
|
|
287
|
+
memory.increment('key', amount, 'namespace')
|
|
236
288
|
```
|
|
237
289
|
|
|
290
|
+
Note: `outputs.history` and `outputs_history` are aliases - both provide access to the full history array for each check.
|
|
291
|
+
|
|
238
292
|
### Complete Example: Multi-Dependent Aggregation
|
|
239
293
|
|
|
240
294
|
The real power of `on_finish` is aggregating results from **multiple** dependent checks:
|
|
241
295
|
|
|
242
296
|
```yaml
|
|
243
|
-
|
|
297
|
+
steps:
|
|
244
298
|
# Step 1: Extract claims from AI response
|
|
245
299
|
extract-claims:
|
|
246
300
|
type: ai
|
|
@@ -340,7 +394,7 @@ This is the **only way** to aggregate across multiple dependent checks in a forE
|
|
|
340
394
|
**Example showing the difference:**
|
|
341
395
|
|
|
342
396
|
```yaml
|
|
343
|
-
|
|
397
|
+
steps:
|
|
344
398
|
extract-items:
|
|
345
399
|
type: command
|
|
346
400
|
forEach: true
|