@probelabs/visor 0.1.131-ee → 0.1.132-ee

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 (94) hide show
  1. package/README.md +460 -596
  2. package/action.yml +2 -2
  3. package/dist/ai-review-service.d.ts +3 -0
  4. package/dist/ai-review-service.d.ts.map +1 -1
  5. package/dist/cli-main.d.ts.map +1 -1
  6. package/dist/config/config-watcher.d.ts +15 -1
  7. package/dist/config/config-watcher.d.ts.map +1 -1
  8. package/dist/enterprise/policy/policy-input-builder.d.ts +2 -0
  9. package/dist/enterprise/policy/policy-input-builder.d.ts.map +1 -1
  10. package/dist/frontends/slack-frontend.d.ts.map +1 -1
  11. package/dist/generated/config-schema.d.ts +404 -96
  12. package/dist/generated/config-schema.d.ts.map +1 -1
  13. package/dist/generated/config-schema.json +2875 -0
  14. package/dist/index.js +23064 -8507
  15. package/dist/providers/ai-check-provider.d.ts +12 -0
  16. package/dist/providers/ai-check-provider.d.ts.map +1 -1
  17. package/dist/providers/workflow-check-provider.d.ts.map +1 -1
  18. package/dist/providers/workflow-tool-executor.d.ts +5 -1
  19. package/dist/providers/workflow-tool-executor.d.ts.map +1 -1
  20. package/dist/sdk/{check-provider-registry-FMHECPI4.mjs → check-provider-registry-7TCA3NSG.mjs} +7 -7
  21. package/dist/sdk/{check-provider-registry-ZOLEYDKM.mjs → check-provider-registry-KUDVEKAC.mjs} +7 -7
  22. package/dist/sdk/{chunk-EBTD2D4L.mjs → chunk-27RV5RR2.mjs} +2 -2
  23. package/dist/sdk/{chunk-UXMMGCAS.mjs → chunk-2RNTEWOA.mjs} +232 -43
  24. package/dist/sdk/chunk-2RNTEWOA.mjs.map +1 -0
  25. package/dist/sdk/{chunk-2GCSK3PD.mjs → chunk-BGBXLPLL.mjs} +3 -3
  26. package/dist/sdk/{chunk-LQ5B4T6L.mjs → chunk-U3BLLEW3.mjs} +431 -82
  27. package/dist/sdk/chunk-U3BLLEW3.mjs.map +1 -0
  28. package/dist/sdk/{chunk-N4I6ZDCJ.mjs → chunk-VG7FWDC2.mjs} +3 -3
  29. package/dist/sdk/chunk-VG7FWDC2.mjs.map +1 -0
  30. package/dist/sdk/{chunk-MQ57AB4U.mjs → chunk-XGI47XIH.mjs} +260 -55
  31. package/dist/sdk/chunk-XGI47XIH.mjs.map +1 -0
  32. package/dist/sdk/{config-4EG7IQIU.mjs → config-FMIIATKX.mjs} +2 -2
  33. package/dist/sdk/{failure-condition-evaluator-GLHZZF47.mjs → failure-condition-evaluator-PNONVBXD.mjs} +3 -3
  34. package/dist/sdk/{github-frontend-F4TE2JY7.mjs → github-frontend-WR4S3NG5.mjs} +3 -3
  35. package/dist/sdk/{host-GOOVFXW6.mjs → host-TROSAWTE.mjs} +3 -3
  36. package/dist/sdk/{host-VA3ET7N6.mjs → host-U7V54J2H.mjs} +3 -3
  37. package/dist/sdk/{loader-ID5LMXOW.mjs → loader-ZC5G3JGJ.mjs} +2 -2
  38. package/dist/sdk/{opa-policy-engine-UUPFN5CL.mjs → opa-policy-engine-S2S2ULEI.mjs} +1 -1
  39. package/dist/sdk/opa-policy-engine-S2S2ULEI.mjs.map +1 -0
  40. package/dist/sdk/{routing-OXQKETSA.mjs → routing-F4FOWVKF.mjs} +4 -4
  41. package/dist/sdk/{schedule-tool-handler-YTBMLVEA.mjs → schedule-tool-handler-ULNF7TZW.mjs} +6 -6
  42. package/dist/sdk/{schedule-tool-handler-PJVKWSYX.mjs → schedule-tool-handler-VFES42DD.mjs} +6 -6
  43. package/dist/sdk/sdk.d.mts +56 -38
  44. package/dist/sdk/sdk.d.ts +56 -38
  45. package/dist/sdk/sdk.js +743 -114
  46. package/dist/sdk/sdk.js.map +1 -1
  47. package/dist/sdk/sdk.mjs +5 -5
  48. package/dist/sdk/{slack-frontend-LAY45IBR.mjs → slack-frontend-JS2VAZWB.mjs} +95 -4
  49. package/dist/sdk/slack-frontend-JS2VAZWB.mjs.map +1 -0
  50. package/dist/sdk/{trace-helpers-R2ETIEC2.mjs → trace-helpers-RDPXIN4S.mjs} +2 -2
  51. package/dist/sdk/{workflow-check-provider-4SA32BO7.mjs → workflow-check-provider-4NFWH6YO.mjs} +7 -7
  52. package/dist/sdk/{workflow-check-provider-57KAR4Y4.mjs → workflow-check-provider-5XS62BCJ.mjs} +7 -7
  53. package/dist/slack/adapter.d.ts +2 -0
  54. package/dist/slack/adapter.d.ts.map +1 -1
  55. package/dist/slack/client.d.ts +3 -0
  56. package/dist/slack/client.d.ts.map +1 -1
  57. package/dist/slack/markdown.d.ts +29 -0
  58. package/dist/slack/markdown.d.ts.map +1 -1
  59. package/dist/slack/socket-runner.d.ts +2 -0
  60. package/dist/slack/socket-runner.d.ts.map +1 -1
  61. package/dist/tui/chat-tui.d.ts +7 -0
  62. package/dist/tui/chat-tui.d.ts.map +1 -1
  63. package/dist/tui/components/input-bar.d.ts +11 -0
  64. package/dist/tui/components/input-bar.d.ts.map +1 -1
  65. package/dist/tui/components/trace-viewer.d.ts +25 -1
  66. package/dist/tui/components/trace-viewer.d.ts.map +1 -1
  67. package/dist/types/bot.d.ts +12 -0
  68. package/dist/types/bot.d.ts.map +1 -1
  69. package/dist/types/config.d.ts +4 -1
  70. package/dist/types/config.d.ts.map +1 -1
  71. package/package.json +3 -3
  72. package/dist/defaults/.visor.yaml +0 -420
  73. package/dist/sdk/chunk-LQ5B4T6L.mjs.map +0 -1
  74. package/dist/sdk/chunk-MQ57AB4U.mjs.map +0 -1
  75. package/dist/sdk/chunk-N4I6ZDCJ.mjs.map +0 -1
  76. package/dist/sdk/chunk-UXMMGCAS.mjs.map +0 -1
  77. package/dist/sdk/opa-policy-engine-UUPFN5CL.mjs.map +0 -1
  78. package/dist/sdk/slack-frontend-LAY45IBR.mjs.map +0 -1
  79. /package/dist/sdk/{check-provider-registry-FMHECPI4.mjs.map → check-provider-registry-7TCA3NSG.mjs.map} +0 -0
  80. /package/dist/sdk/{check-provider-registry-ZOLEYDKM.mjs.map → check-provider-registry-KUDVEKAC.mjs.map} +0 -0
  81. /package/dist/sdk/{chunk-EBTD2D4L.mjs.map → chunk-27RV5RR2.mjs.map} +0 -0
  82. /package/dist/sdk/{chunk-2GCSK3PD.mjs.map → chunk-BGBXLPLL.mjs.map} +0 -0
  83. /package/dist/sdk/{config-4EG7IQIU.mjs.map → config-FMIIATKX.mjs.map} +0 -0
  84. /package/dist/sdk/{failure-condition-evaluator-GLHZZF47.mjs.map → failure-condition-evaluator-PNONVBXD.mjs.map} +0 -0
  85. /package/dist/sdk/{github-frontend-F4TE2JY7.mjs.map → github-frontend-WR4S3NG5.mjs.map} +0 -0
  86. /package/dist/sdk/{host-GOOVFXW6.mjs.map → host-TROSAWTE.mjs.map} +0 -0
  87. /package/dist/sdk/{host-VA3ET7N6.mjs.map → host-U7V54J2H.mjs.map} +0 -0
  88. /package/dist/sdk/{loader-ID5LMXOW.mjs.map → loader-ZC5G3JGJ.mjs.map} +0 -0
  89. /package/dist/sdk/{routing-OXQKETSA.mjs.map → routing-F4FOWVKF.mjs.map} +0 -0
  90. /package/dist/sdk/{schedule-tool-handler-PJVKWSYX.mjs.map → schedule-tool-handler-ULNF7TZW.mjs.map} +0 -0
  91. /package/dist/sdk/{schedule-tool-handler-YTBMLVEA.mjs.map → schedule-tool-handler-VFES42DD.mjs.map} +0 -0
  92. /package/dist/sdk/{trace-helpers-R2ETIEC2.mjs.map → trace-helpers-RDPXIN4S.mjs.map} +0 -0
  93. /package/dist/sdk/{workflow-check-provider-4SA32BO7.mjs.map → workflow-check-provider-4NFWH6YO.mjs.map} +0 -0
  94. /package/dist/sdk/{workflow-check-provider-57KAR4Y4.mjs.map → workflow-check-provider-5XS62BCJ.mjs.map} +0 -0
package/README.md CHANGED
@@ -1,36 +1,96 @@
1
1
  <div align="center">
2
2
  <img src="site/visor.png" alt="Visor Logo" width="500" />
3
-
4
- # Visor — Open‑source SDLC automation & code review orchestration
5
-
3
+
4
+ # Visor — AI workflow engine for code review, assistants & automation
5
+
6
6
  [![TypeScript](https://img.shields.io/badge/TypeScript-5.0%2B-blue)](https://www.typescriptlang.org/)
7
7
  [![Node](https://img.shields.io/badge/Node.js-18%2B-green)](https://nodejs.org/)
8
8
  [![License](https://img.shields.io/badge/license-MIT-blue)](LICENSE)
9
-
10
- Config‑driven checks and automations with native GitHub checks/annotations.
11
- PR reviews, issue assistants, release notes, scheduled audits, and webhooks.
12
- AI‑assisted when you want it, fully predictable when you don’t.
9
+
10
+ Orchestrate checks, MCP tools, and AI providers with YAML-driven pipelines.
11
+ Runs as GitHub Action, CLI, Slack bot, or HTTP API.
13
12
  </div>
14
13
 
15
14
  ---
16
15
 
17
- Visor ships with a ready-to-run configuration at `defaults/.visor.yaml`, so you immediately get:
18
- - A staged review pipeline (`overview → security → performance → quality → style`).
19
- - Native GitHub integration: check runs, annotations, and PR comments out of the box.
20
- - Built‑in code assistant: trigger via PR/issue comments (e.g., `/visor how it works?`).
21
- - A manual release-notes generator for tagged release workflows.
22
- - No magic: everything is config‑driven in `.visor.yaml`; prompts/context are visible and templatable.
23
- - Built for scale: composable checks, tag-based profiles, and flexible `extends` for shared policies.
16
+ Visor is an open-source workflow engine that lets you define multi-step AI pipelines in YAML. Wire up shell commands, AI providers, MCP tools, HTTP calls, and custom scripts into dependency-aware DAGs — then run them from your terminal, CI, Slack, or an HTTP endpoint.
17
+
18
+ **What you get out of the box:**
19
+
20
+ - **YAML-driven pipelines** define checks, transforms, routing, and AI prompts in a single config file.
21
+ - **4 runtime modes** CLI, GitHub Action, Slack bot, HTTP server — same config, any surface.
22
+ - **12+ provider types** `ai`, `command`, `script`, `mcp`, `http`, `claude-code`, `github`, `memory`, `workflow`, and more.
23
+ - **AI orchestration** — multi-provider (Gemini, Claude, OpenAI, Bedrock), session reuse, MCP tool calling, retry & fallback.
24
+ - **Execution engine** — dependency DAGs, parallel waves, forEach fan-out, conditional routing, failure auto-remediation.
25
+ - **Built-in testing** — YAML-native integration tests with fixtures, mocks, and assertions.
26
+
27
+ ## Table of Contents
28
+
29
+ - [Quick Start](#-quick-start)
30
+ - [Runtime Modes](#-runtime-modes)
31
+ - [PR Comment Commands](#-pr-comment-commands)
32
+ - [Core Concepts](#-core-concepts)
33
+ - [Provider Types](#-provider-types)
34
+ - [Orchestration](#-orchestration)
35
+ - [AI & MCP](#-ai--mcp)
36
+ - [GitHub Provider](#-github-provider)
37
+ - [Templating & Transforms](#-templating--transforms)
38
+ - [Suppressing Warnings](#-suppressing-warnings)
39
+ - [Testing Framework](#-testing-framework)
40
+ - [SDK](#-sdk-programmatic-usage)
41
+ - [Configuration](#-configuration)
42
+ - [Observability](#-observability)
43
+ - [Security](#-security)
44
+ - [Enterprise Policy Engine](#-enterprise-policy-engine-ee)
45
+ - [Further Reading](#-further-reading)
46
+ - [Contributing](#-contributing)
47
+ - [License](#-license)
48
+
49
+ **Requirements:** Node.js 18+ (CI runs Node 20).
50
+
51
+ ## 🚀 Quick Start
52
+
53
+ ### Install & Run
54
+
55
+ ```bash
56
+ # One-off
57
+ npx -y @probelabs/visor@latest --check all --output table
58
+
59
+ # As a dev dependency
60
+ npm i -D @probelabs/visor
61
+ npx visor --check all --output json
62
+ ```
63
+
64
+ ### Minimal Config (`.visor.yaml`)
65
+
66
+ ```yaml
67
+ version: "1.0"
68
+ steps:
69
+ security:
70
+ type: ai
71
+ prompt: "Identify security issues in changed files"
72
+ tags: ["fast", "security"]
73
+
74
+ run-tests:
75
+ type: command
76
+ exec: npm test
77
+ depends_on: [security]
24
78
 
25
- ## 🚀 90-second Quick Start
79
+ notify:
80
+ type: http
81
+ method: POST
82
+ url: https://hooks.slack.com/...
83
+ body: '{ "text": "Tests {{ outputs[''run-tests''].status }}" }'
84
+ depends_on: [run-tests]
85
+ ```
26
86
 
27
- ### Add the Action
87
+ ### As a GitHub Action
28
88
 
29
89
  ```yaml
30
90
  # .github/workflows/visor.yml
31
91
  name: Visor
32
92
  on:
33
- pull_request: { types: [opened, synchronize] } # For fork PRs, see docs/GITHUB_CHECKS.md
93
+ pull_request: { types: [opened, synchronize] }
34
94
  issues: { types: [opened] }
35
95
  issue_comment: { types: [created] }
36
96
  permissions:
@@ -45,743 +105,576 @@ jobs:
45
105
  - uses: actions/checkout@v4
46
106
  - uses: probelabs/visor@v1
47
107
  env:
48
- GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }} # or ANTHROPIC/OPENAI
108
+ GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}
49
109
  ```
50
110
 
51
- ### Open a PR
52
- - Visor posts a PR summary, creates GitHub Check runs, and annotates lines.
53
- - **Note**: For external contributor PRs from forks, check runs may not be available due to GitHub security restrictions. Visor will gracefully fall back to PR comments. See [Fork PR Support](docs/GITHUB_CHECKS.md#fork-pr-support) for how to enable check runs for forks.
54
-
55
- ### Optional: Add `.visor.yaml`
56
-
57
- ```yaml
58
- version: "1.0"
59
- steps: # or 'checks' (legacy, both work identically)
60
- security:
61
- type: ai
62
- schema: code-review
63
- prompt: "Identify security issues in changed files"
64
- tags: ["fast", "security"]
65
- ```
66
-
67
- Tip: Pin releases for stability, e.g. `uses: probelabs/visor@v1`.
68
- For latest changes, use `uses: probelabs/visor@nightly`. The `@main` ref is maintained for compatibility but may change frequently and is not recommended for production.
69
-
70
- ## Requirements
111
+ > **Tip:** Pin releases for stability with `@v1`. For bleeding-edge, use `@nightly`.
71
112
 
72
- - Node.js 18+ (CI runs Node 20)
73
- - When used as a GitHub Action: appropriate permissions/secrets (see [Security Defaults](#-security-defaults))
113
+ ## 🖥️ Runtime Modes
74
114
 
75
- ## Installation
115
+ Visor runs the same YAML config across four surfaces:
76
116
 
77
- - One‑off run
78
- ```bash
79
- npx -y @probelabs/visor@latest --check all --output table
80
- ```
81
- - Project dev dependency
82
- ```bash
83
- npm i -D @probelabs/visor
84
- npx visor --check all --output json
85
- ```
117
+ | Mode | How to run | Best for |
118
+ |------|-----------|----------|
119
+ | **CLI** | `visor --check all --output table` | Local dev, CI pipelines |
120
+ | **GitHub Action** | `uses: probelabs/visor@v1` | PR reviews, issue triage, annotations |
121
+ | **Slack bot** | `visor --slack --config .visor.yaml` | Team assistants, ChatOps |
122
+ | **HTTP server** | `http_server: { enabled: true, port: 8080 }` | Webhooks, API integrations |
86
123
 
87
- ## 📋 CLI Usage
88
-
89
- Short cheatsheet for common tasks:
124
+ Additional modes:
125
+ - **TUI** — interactive chat-style terminal UI: `visor --tui`
126
+ - **SDK** programmatic Node.js API: `import { runChecks } from '@probelabs/visor/sdk'`
127
+ - **Scheduler** — cron-based execution with database-backed persistence
90
128
 
91
129
  ```bash
92
- # Validate configuration before running checks
93
- visor validate # Search for .visor.yaml in current directory
94
- visor validate --config .visor.yaml # Validate specific config file
95
-
96
- # Run all checks with a table output
130
+ # CLI examples
97
131
  visor --check all --output table
98
-
99
- # Interactive TUI mode (chat-style interface for human-input workflows)
100
- visor --tui --config ./my-workflow.yaml
101
-
102
- # Filter by tags (e.g., fast/local) and increase parallelism
103
132
  visor --tags fast,local --max-parallelism 5
133
+ visor --analyze-branch-diff # PR-style diff analysis
134
+ visor --event pr_updated # Simulate GitHub events
135
+ visor --tui --config ./workflow.yaml # Interactive TUI
136
+ visor --debug-server --debug-port 3456 # Live web debugger
137
+ visor config snapshots # Config version history
138
+ visor validate # Validate config
139
+ visor test --progress compact # Run integration tests
140
+ ```
104
141
 
105
- # Analyze full PR diff vs base branch (like GitHub Actions does)
106
- # Auto-enabled for code-review schemas, or force with --analyze-branch-diff
107
- visor --analyze-branch-diff # Analyzes diff vs main/master branch
108
- visor --check security --analyze-branch-diff # Specific checks on branch diff
109
-
110
- # Simulate GitHub events for event-based check filtering
111
- visor --event pr_updated # Run checks triggered by PR updates (auto for code-review)
112
- visor --event issue_opened # Run checks triggered by new issues
113
- visor --event all # Run all checks regardless of event filters (default)
114
-
115
- # Emit machine‑readable results and save to a file
116
- visor --check security --output json --output-file visor-results.json
142
+ **Run modes:** Default is CLI mode everywhere. For GitHub-specific behavior (comments, checks, annotations), run with `--mode github-actions` or set `mode: github-actions` in the Action. Force CLI mode inside Actions with `VISOR_MODE=cli`.
117
143
 
118
- # Visual debugger with web UI
119
- visor --debug-server --debug-port 3456
144
+ See [docs/commands.md](docs/commands.md) for the full CLI reference.
120
145
 
121
- # Config snapshots list, diff, or restore saved configurations
122
- visor config snapshots
123
- visor config diff 1 2
146
+ ## 💬 PR Comment Commands
124
147
 
125
- # Live config reload in long-running modes (e.g. Slack)
126
- visor --slack --config .visor.yaml --watch
148
+ Trigger reviews and assistant actions via comments on PRs or issues:
127
149
 
128
- # Discover options
129
- visor --help
150
+ ```
151
+ /review # Re-run all checks
152
+ /review --check security # Re-run specific check
153
+ /visor how does caching work? # Ask the built-in assistant
130
154
  ```
131
155
 
132
- See full CLI options: [docs/commands.md](docs/commands.md)
133
-
134
- Additional guides:
135
-
136
- - debugging and local development (TUI, debug server): [docs/debugging.md](docs/debugging.md)
137
- - fail conditions: [docs/fail-if.md](docs/fail-if.md)
138
- - forEach behavior and dependent propagation (including outputs_raw and history precedence): [docs/foreach-dependency-propagation.md](docs/foreach-dependency-propagation.md)
139
- - Failure routing and `on_finish` (with outputs_raw in routing JS): [docs/failure-routing.md](docs/failure-routing.md)
140
- - timeouts and provider units: [docs/timeouts.md](docs/timeouts.md)
141
- - execution limits (run caps for safety): [docs/limits.md](docs/limits.md)
142
- - output formatting limits and truncation controls: [docs/output-formatting.md](docs/output-formatting.md)
143
- - live execution visualizer and control API: [docs/debug-visualizer.md](docs/debug-visualizer.md)
144
- - scheduler for cron jobs and dynamic schedules: [docs/scheduler.md](docs/scheduler.md)
145
-
146
- ## 🧪 Integration Tests
147
-
148
- Write and run integration tests for your Visor config in YAML. No network, built‑in GitHub fixtures, strict by default, and great CLI output.
156
+ Learn more: [docs/commands.md](docs/commands.md)
149
157
 
150
- - Getting started: [docs/testing/getting-started.md](docs/testing/getting-started.md)
151
- - DSL reference: [docs/testing/dsl-reference.md](docs/testing/dsl-reference.md)
152
- - Flows: [docs/testing/flows.md](docs/testing/flows.md)
153
- - Fixtures & mocks: [docs/testing/fixtures-and-mocks.md](docs/testing/fixtures-and-mocks.md)
154
- - Assertions: [docs/testing/assertions.md](docs/testing/assertions.md)
155
- - Cookbook: [docs/testing/cookbook.md](docs/testing/cookbook.md)
156
- - CLI & reporters: [docs/testing/cli.md](docs/testing/cli.md)
157
- - CI integration: [docs/testing/ci.md](docs/testing/ci.md)
158
- - Troubleshooting: [docs/testing/troubleshooting.md](docs/testing/troubleshooting.md)
158
+ ## 🧩 Core Concepts
159
+
160
+ | Concept | What it is |
161
+ |---------|-----------|
162
+ | **Step** (or Check) | Unit of work — a shell command, AI call, HTTP request, script, etc. |
163
+ | **Provider** | How a step runs: `ai`, `command`, `script`, `mcp`, `http`, `claude-code`, `github`, `memory`, `workflow`, … |
164
+ | **depends_on** | Execution order — independents run in parallel, dependents wait. |
165
+ | **forEach** | Fan-out transform output into an array, run dependents per item. |
166
+ | **Routing** | `on_fail`, `on_success`, `goto`, `retry` — conditional flow with loop safety. |
167
+ | **Transform** | Reshape output with Liquid templates or JavaScript before passing downstream. |
168
+ | **Schema** | JSON Schema that validates step output (e.g., `code-review`). |
169
+ | **Template** | Renders validated output into Markdown/table for PR comments. |
170
+ | **Group** | Which PR comment a step posts into. |
171
+ | **Tags** | Label steps and filter with `--tags fast,local`. |
172
+ | **Events** | Trigger steps on PRs, issues, comments, webhooks, or cron schedules. |
173
+
174
+ ## 🔌 Provider Types
175
+
176
+ | Provider | Description | Example use |
177
+ |----------|------------|------------|
178
+ | `ai` | Multi-provider AI (Gemini, Claude, OpenAI, Bedrock) | Code review, analysis, generation |
179
+ | `command` | Shell commands with Liquid templating | Run tests, build, lint |
180
+ | `script` | JavaScript in a secure sandbox | Transform data, custom logic |
181
+ | `mcp` | MCP tool execution (stdio/SSE/HTTP) | External tool integration |
182
+ | `claude-code` | Claude Code SDK with MCP tools | Deep code analysis, refactoring |
183
+ | `http` | HTTP output/webhook sender | Notify Slack, trigger CI |
184
+ | `http_input` | Webhook receiver | Accept external events |
185
+ | `http_client` | HTTP API client | Call external APIs |
186
+ | `github` | GitHub operations (labels, comments, checks) | Label PRs, post reviews |
187
+ | `memory` | Key-value store (get/set/append/increment) | State across steps |
188
+ | `workflow` | Reusable sub-workflows from files/URLs | Compose pipelines |
189
+ | `human-input` | Interactive prompts (TUI/Slack) | Approvals, user input |
190
+ | `log` / `logger` | Structured logging | Debug, audit trail |
191
+ | `noop` | No-op placeholder | Orchestration nodes |
192
+ | `git-checkout` | Git operations (clone, checkout, worktree) | Multi-repo workflows |
193
+
194
+ See [docs/pluggable.md](docs/pluggable.md) for building custom providers.
195
+
196
+ ## ⚙️ Orchestration
197
+
198
+ ### Dependencies & Parallel Execution
199
+
200
+ Steps without dependencies run in parallel waves. `depends_on` enforces ordering:
159
201
 
160
- Note: examples use descriptive step names (e.g., `extract-facts`, `validate-fact`) to illustrate patterns. These are not built‑ins; the test runner works with whatever steps you define in `.visor.yaml`.
202
+ ```yaml
203
+ steps:
204
+ fetch-data:
205
+ type: command
206
+ exec: curl -s https://api.example.com/data
161
207
 
162
- ## 🧩 Core Concepts (1 minute)
208
+ analyze:
209
+ type: ai
210
+ prompt: "Analyze: {{ outputs['fetch-data'] }}"
211
+ depends_on: [fetch-data]
163
212
 
164
- - Check – unit of work (`security`, `performance`).
165
- - Schema – JSON shape checks return (e.g., `code-review`).
166
- - Template renders results (tables/markdown).
167
- - Group – which comment a check is posted into.
168
- - Provider – how a check runs (`ai`, `mcp`, `http`, `http_client`, `command`, `log`, `github`, `claude-code`).
169
- - Dependencies – `depends_on` controls order; independents run in parallel.
170
- - Tags – label checks (`fast`, `local`, `comprehensive`) and filter with `--tags`.
171
- - Events – PRs, issues, `/review` comments, webhooks, or cron schedules.
213
+ report:
214
+ type: command
215
+ exec: 'echo "Done: {{ outputs[''analyze''] | truncate: 100 }}"'
216
+ depends_on: [analyze]
217
+ ```
172
218
 
173
- ## Beyond Code Review
219
+ ### forEach Fan-Out
174
220
 
175
- Visor is a general SDLC automation framework:
176
- - PR Reviews – security/perf/style findings with native annotations
177
- - Issue Assistant – `/visor …` for code Q&A and triage
178
- - Release Notes – manual or tagged release workflows
179
- - Scheduled Audits – cron‑driven checks against main
180
- - Webhooks & HTTP – receive events, call APIs, and post results
181
- - Policy‑as‑Code – schemas + templates for predictable, auditable outputs
221
+ Transform output into an array, run dependents once per item:
182
222
 
183
- ## Table of Contents
223
+ ```yaml
224
+ steps:
225
+ list-services:
226
+ type: command
227
+ exec: 'echo ''["auth","payments","notifications"]'''
228
+ forEach: true
184
229
 
185
- - [90‑second Quick Start](#-90-second-quick-start)
186
- - [Requirements](#requirements)
187
- - [Installation](#installation)
188
- - [CLI Usage](#-cli-usage)
189
- - [Core Concepts (1 minute)](#-core-concepts-1-minute)
190
- - [Beyond Code Review](#beyond-code-review)
191
- - [Features](#-features)
192
- - [When to pick Visor](#when-to-pick-visor)
193
- - [Developer Experience Playbook](#-developer-experience-playbook)
194
- - [Tag-Based Check Filtering](#-tag-based-check-filtering)
195
- - [PR Comment Commands](#-pr-comment-commands)
196
- - [Enterprise Policy Engine (EE)](#-enterprise-policy-engine-ee)
197
- - [Suppressing Warnings](#-suppressing-warnings)
198
- - [Troubleshooting](#-troubleshooting)
199
- - [Security Defaults](#-security-defaults)
200
- - [Performance & Cost Controls](#-performance--cost-controls)
201
- - [Observability](#-observability)
202
- - [AI Configuration](#-ai-configuration)
203
- - [Step Dependencies & Intelligent Execution](#-step-dependencies--intelligent-execution)
204
- - [Failure Routing (Auto-fix Loops)](#-failure-routing-auto-fix-loops)
205
- - [Claude Code Provider](#-claude-code-provider)
206
- - [GitHub Provider](#-github-provider)
207
- - [AI Session Reuse](#-ai-session-reuse)
208
- - [Schema-Template System](#-schema-template-system)
209
- - [Enhanced Prompts](#-enhanced-prompts)
210
- - [SDK (Programmatic Usage)](#-sdk-programmatic-usage)
211
- - [Debugging](#-debugging)
212
- - [Advanced Configuration](#-advanced-configuration)
213
- - [HTTP Integration & Scheduling](#-http-integration--scheduling)
214
- - [Pluggable Architecture](#-pluggable-architecture)
215
- - [GitHub Action Reference](#-github-action-reference)
216
- - [Output Formats](#-output-formats)
217
- - [Contributing](#-contributing)
218
- - [Further Reading](#-further-reading)
219
- - [License](#-license)
220
-
221
- ## ✨ Features
222
-
223
- - Native GitHub reviews: Check runs, inline annotations, and status reporting wired into PRs.
224
- - Config‑first: One `.visor.yaml` defines checks, prompts, schemas, and templates — no hidden logic.
225
- - Structured outputs: JSON Schema validation drives deterministic rendering, annotations, and SARIF.
226
- - Orchestrated pipelines: Dependencies, parallelism, and tag‑based profiles; run in Actions or any CI.
227
- - Multi‑provider AI: Google Gemini, Anthropic Claude, OpenAI, AWS Bedrock — plus MCP tools, standalone MCP provider, and Claude Code SDK.
228
- - Author permissions: Built-in functions to customize workflows based on contributor trust level (owner, member, collaborator, etc).
229
- - Assistants & commands: `/review` to rerun checks, `/visor …` for Q&A, predictable comment groups.
230
- - HTTP & schedules: Receive webhooks, call external APIs, and run cron‑scheduled audits and reports.
231
- - Extensible providers: `ai`, `mcp`, `http`, `http_client`, `log`, `command`, `github`, `claude-code`, `human-input`, `memory` — or add your own.
232
- - Security by default: GitHub App support, scoped tokens, remote‑extends allowlist, opt‑in network usage.
233
- - Observability & control: JSON/SARIF outputs, fail‑fast and timeouts, parallelism and cost control.
234
-
235
- ## When to pick Visor
236
-
237
- - You want native GitHub checks/annotations and config‑driven behavior
238
- - You need structured outputs (schemas) and predictable templates
239
- - You care about dependency‑aware execution and tag‑based profiles
240
- - You want PR reviews + assistants + scheduled audits from one tool
241
- - You prefer open‑source with no hidden rules
242
-
243
- ## 🧭 Developer Experience Playbook
244
-
245
- Start with the defaults, iterate locally, and commit a shared `.visor.yaml` for your team.
246
-
247
- Example:
248
- ```bash
249
- npx -y @probelabs/visor@latest --check all --debug
230
+ check-service:
231
+ type: command
232
+ exec: 'curl -s https://{{ outputs["list-services"] }}/health'
233
+ depends_on: [list-services]
250
234
  ```
251
235
 
252
- Learn more: [docs/dev-playbook.md](docs/dev-playbook.md)
253
-
254
- ## 🏷️ Tag-Based Check Filtering
236
+ Use `outputs_raw` in downstream steps to access the aggregated array of all forEach results:
255
237
 
256
- Run subsets of checks (e.g., `local`, `fast`, `security`) and select them per environment with `--tags`/`--exclude-tags`.
257
-
258
- Example:
259
238
  ```yaml
260
- steps:
261
- security-quick:
262
- type: ai
263
- prompt: "Quick security scan"
264
- tags: ["local", "fast", "security"]
239
+ summarize:
240
+ type: script
241
+ depends_on: [list-services]
242
+ content: |
243
+ const arr = outputs_raw['list-services'] || [];
244
+ return { total: arr.length };
265
245
  ```
266
246
 
267
- CLI:
268
- ```bash
269
- visor --tags local,fast
270
- ```
247
+ Learn more: [docs/foreach-dependency-propagation.md](docs/foreach-dependency-propagation.md)
271
248
 
272
- Learn more: [docs/tag-filtering.md](docs/tag-filtering.md)
249
+ ### Failure Routing & Auto-Remediation
273
250
 
274
- ## 💬 PR Comment Commands
251
+ Steps can retry, run remediation, or jump to other steps on failure:
275
252
 
276
- Trigger reviews and assistant actions via comments on PRs/issues.
253
+ ```yaml
254
+ version: "2.0"
255
+ routing:
256
+ max_loops: 5
257
+ steps:
258
+ build:
259
+ type: command
260
+ exec: make build
261
+ on_fail:
262
+ retry: { max: 2, backoff: { mode: exponential, delay_ms: 500 } }
263
+ goto: setup # Jump back on exhausted retries
277
264
 
278
- Examples:
279
- ```
280
- /review
281
- /review --check security
282
- /visor how does caching work?
265
+ deploy:
266
+ type: command
267
+ exec: make deploy
268
+ depends_on: [build]
269
+ on_success:
270
+ run: [notify] # Run extra steps on success
271
+ on_fail:
272
+ goto_js: |
273
+ return attempt <= 2 ? 'build' : null; # Dynamic routing
283
274
  ```
284
275
 
285
- Learn more: [docs/commands.md](docs/commands.md)
286
-
287
- ## 🔐 Author Permissions
276
+ Learn more: [docs/failure-routing.md](docs/failure-routing.md)
288
277
 
289
- Customize workflows based on PR author's permission level using built-in functions in JavaScript expressions:
278
+ ### Conditional Execution & Author Permissions
290
279
 
291
280
  ```yaml
292
281
  steps:
293
- # Run security scan only for external contributors
294
282
  security-scan:
295
283
  type: command
296
- exec: npm run security:full
297
- if: "!hasMinPermission('MEMBER')"
284
+ exec: npm audit
285
+ if: "!hasMinPermission('MEMBER')" # Only for external contributors
298
286
 
299
- # Auto-approve PRs from collaborators
300
287
  auto-approve:
301
- type: command
302
- exec: gh pr review --approve
288
+ type: github
289
+ op: labels.add
290
+ values: ["approved"]
303
291
  if: "hasMinPermission('COLLABORATOR') && totalIssues === 0"
304
292
 
305
- # Block sensitive file changes from non-members
306
293
  protect-secrets:
307
294
  type: command
308
295
  exec: echo "Checking permissions..."
309
296
  fail_if: "!isMember() && files.some(f => f.filename.startsWith('secrets/'))"
310
297
  ```
311
298
 
312
- **Available functions:**
313
- - `hasMinPermission(level)` - Check if author has >= permission level
314
- - `isOwner()`, `isMember()`, `isCollaborator()`, `isContributor()`, `isFirstTimer()` - Boolean checks
299
+ Available permission functions: `hasMinPermission(level)`, `isOwner()`, `isMember()`, `isCollaborator()`, `isContributor()`, `isFirstTimer()`.
315
300
 
316
301
  Learn more: [docs/author-permissions.md](docs/author-permissions.md)
317
302
 
318
- ## 🏢 Enterprise Policy Engine (EE)
319
-
320
- > **Enterprise Edition feature.** Requires a Visor EE license. Contact **hello@probelabs.com**.
303
+ ## 🤖 AI & MCP
321
304
 
322
- Add OPA-based role-based access control to gate checks, MCP tools, and AI capabilities using [Rego](https://www.openpolicyagent.org/docs/latest/policy-language/) policies.
305
+ ### Multi-Provider AI
323
306
 
324
307
  ```yaml
325
- policy:
326
- engine: local
327
- rules: ./policies/
328
- fallback: deny
329
- roles:
330
- admin:
331
- author_association: [OWNER]
332
- developer:
333
- author_association: [MEMBER, COLLABORATOR]
334
- ```
335
-
336
- Checks denied by policy are skipped with reason `policy_denied`. Without a valid license, the engine silently disables and all checks run normally.
337
-
338
- Learn more: [docs/enterprise-policy.md](docs/enterprise-policy.md) | [examples/enterprise-policy/](examples/enterprise-policy/)
339
-
340
- ## 🔇 Suppressing Warnings
341
-
342
- Suppress a specific issue by adding a nearby `visor-disable` comment.
343
-
344
- Example (JS):
345
- ```js
346
- const testPassword = "demo123"; // visor-disable
347
- ```
348
-
349
- Learn more: [docs/suppressions.md](docs/suppressions.md)
350
-
351
- ## 🛠️ Troubleshooting
352
-
353
- If comments/annotations don’t appear, verify workflow permissions and run with `--debug`.
354
-
355
- Example:
356
- ```bash
357
- node dist/index.js --cli --check all --debug
308
+ steps:
309
+ review:
310
+ type: ai
311
+ prompt: "Review this code for security issues"
312
+ ai:
313
+ provider: anthropic # or: google, openai, bedrock
314
+ model: claude-sonnet-4-20250514
315
+ fallback:
316
+ strategy: any # Try other providers on failure
358
317
  ```
359
318
 
360
- Run modes
319
+ Supported providers: **Google Gemini**, **Anthropic Claude**, **OpenAI GPT**, **AWS Bedrock**.
361
320
 
362
- - Default is CLI mode everywhere (no auto-detection).
363
- - For GitHub-specific behavior (comments, checks), run with `--mode github-actions` or set `with: mode: github-actions` when using the GitHub Action.
321
+ Set one key via environment: `GOOGLE_API_KEY`, `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, or AWS credentials.
364
322
 
365
- Examples:
323
+ ### MCP Tool Integration
366
324
 
367
- ```bash
368
- # Local/CI CLI
369
- npx -y @probelabs/visor@latest --config .visor.yaml --check all --output json
370
-
371
- # GitHub Actions behavior from any shell/CI
372
- npx -y @probelabs/visor@latest --mode github-actions --config .visor.yaml --check all
373
- ```
374
-
375
- GitHub Action usage:
376
-
377
- ```yaml
378
- - uses: probelabs/visor@vX
379
- with:
380
- mode: github-actions
381
- checks: all
382
- output-format: json
383
- ```
384
-
385
- To force CLI mode inside a GitHub Action step, you can still use:
325
+ Give AI steps access to MCP tools, or call MCP tools directly:
386
326
 
387
327
  ```yaml
388
- env:
389
- VISOR_MODE: cli
390
- ```
391
-
392
- Learn more: [docs/troubleshooting.md](docs/troubleshooting.md)
393
-
394
- ## 🔐 Security Defaults
395
-
396
- Prefer a GitHub App for production, and restrict remote extends unless explicitly allowed.
397
-
398
- Examples:
399
- ```bash
400
- visor --no-remote-extends
401
- visor --allowed-remote-patterns "https://raw.githubusercontent.com/myorg/"
402
- ```
403
-
404
- Learn more: [docs/security.md](docs/security.md)
405
-
406
- ## ⚡ Performance & Cost Controls
407
-
408
- Use tags for fast lanes and raise parallelism cautiously.
328
+ # AI step with MCP tools
329
+ steps:
330
+ analyze:
331
+ type: ai
332
+ prompt: "Use the search tool to find security patterns"
333
+ ai:
334
+ mcp_servers:
335
+ - name: code-search
336
+ command: npx
337
+ args: ["-y", "@probe/search"]
409
338
 
410
- Example:
411
- ```bash
412
- visor --tags local,fast --max-parallelism 5
339
+ # Direct MCP tool execution
340
+ search:
341
+ type: mcp
342
+ transport: stdio
343
+ command: npx
344
+ args: ["-y", "@probe/search"]
345
+ method: search
346
+ arguments:
347
+ query: "{{ outputs['setup'].pattern }}"
413
348
  ```
414
349
 
415
- Learn more: [docs/performance.md](docs/performance.md)
350
+ ### AI Session Reuse
416
351
 
417
- ## 👀 Observability
352
+ Chain AI conversations across steps:
418
353
 
419
- Use JSON for pipelines or SARIF for code scanning. To avoid any chance of logs mixing with the result stream, prefer the built‑in `--output-file`.
354
+ ```yaml
355
+ steps:
356
+ security:
357
+ type: ai
358
+ prompt: "Find security issues"
420
359
 
421
- Examples:
422
- ```bash
423
- visor --check security --output json --output-file visor-results.json
424
- visor --check security --output sarif --output-file visor-results.sarif
360
+ remediation:
361
+ type: ai
362
+ prompt: "Suggest fixes for the issues you found"
363
+ depends_on: [security]
364
+ reuse_ai_session: true # Carries conversation history
365
+ session_mode: append # Or: clone (default)
425
366
  ```
426
367
 
427
- Learn more: [docs/observability.md](docs/observability.md)
428
-
429
- ## 🤖 AI Configuration
368
+ ### Claude Code Provider
430
369
 
431
- Set one provider key (Google/Anthropic/OpenAI/AWS Bedrock) via env.
370
+ Full Claude Code SDK integration with MCP tools and subagents:
432
371
 
433
- Example (Action):
434
372
  ```yaml
435
- - uses: probelabs/visor@v1
436
- env:
437
- GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}
438
- # Or for AWS Bedrock:
439
- # AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
440
- # AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
441
- # AWS_REGION: us-east-1
373
+ steps:
374
+ deep-review:
375
+ type: claude-code
376
+ prompt: "Analyze code complexity and suggest refactoring"
377
+ max_turns: 10
378
+ mcp_servers:
379
+ - name: filesystem
380
+ command: npx
381
+ args: ["-y", "@modelcontextprotocol/server-filesystem", "."]
442
382
  ```
443
383
 
444
- Learn more: [docs/ai-configuration.md](docs/ai-configuration.md)
384
+ Learn more: [docs/claude-code.md](docs/claude-code.md) · [docs/mcp-provider.md](docs/mcp-provider.md) · [docs/advanced-ai.md](docs/advanced-ai.md)
445
385
 
446
- ## 📊 Step Dependencies & Intelligent Execution
386
+ ## 🧰 GitHub Provider
447
387
 
448
- Define `depends_on` to enforce order; independent checks run in parallel.
388
+ Native GitHub operations (labels, comments, checks) without shelling out to `gh`:
449
389
 
450
- Example:
451
390
  ```yaml
452
391
  steps:
453
- security: { type: ai }
454
- performance:{ type: ai, depends_on: [security] }
392
+ apply-labels:
393
+ type: github
394
+ op: labels.add
395
+ values:
396
+ - "{{ outputs.overview.tags.label | default: '' | safe_label }}"
397
+ value_js: |
398
+ return values.filter(v => typeof v === 'string' && v.trim().length > 0);
455
399
  ```
456
400
 
457
- Learn more: [docs/dependencies.md](docs/dependencies.md). See also: [forEach dependency propagation](docs/foreach-dependency-propagation.md)
401
+ Learn more: [docs/github-ops.md](docs/github-ops.md)
458
402
 
459
- Quick example (outputs_raw):
403
+ ## 🧬 Templating & Transforms
460
404
 
461
- ```yaml
462
- version: "2.0"
463
- checks:
464
- list:
465
- type: command
466
- exec: echo '["a","b","c"]'
467
- forEach: true
405
+ ### Liquid Templates
468
406
 
469
- summarize:
470
- type: script
471
- depends_on: [list]
472
- content: |
473
- const arr = outputs_raw['list'] || [];
474
- return { total: arr.length };
407
+ Steps can use Liquid templates in prompts, exec commands, HTTP bodies, and more:
475
408
 
476
- branch-by-size:
477
- type: script
478
- depends_on: [list]
479
- content: 'return true'
480
- on_success:
481
- goto_js: |
482
- return (outputs_raw['list'] || []).length >= 3 ? 'after' : null;
409
+ ```yaml
410
+ steps:
411
+ greet:
412
+ type: command
413
+ exec: 'echo "Files changed: {{ files | size }}, branch: {{ branch }}"'
483
414
 
484
- after:
485
- type: log
486
- message: bulk mode reached
415
+ post-results:
416
+ type: http
417
+ url: https://api.example.com/results
418
+ body: |
419
+ { "issues": {{ outputs["review"] | json }},
420
+ "pr": {{ pr.number }} }
487
421
  ```
488
422
 
489
- ## 🔄 Failure Routing (Auto-fix Loops)
423
+ Available context: `outputs`, `outputs_raw`, `inputs`, `pr`, `files`, `env`, `memory`, `branch`, `event`, `conversation`.
490
424
 
491
- Automatically remediate failures and re‑run steps using config‑driven routing:
425
+ ### JavaScript Transforms
492
426
 
493
- - Per‑step `on_fail` and `on_success` actions:
494
- - `retry` with fixed/exponential backoff (+ deterministic jitter)
495
- - `run`: remediation steps (single or list)
496
- - `goto`: jump back to an ancestor step and continue forward
497
- - `goto_js` / `run_js`: dynamic routing with safe, synchronous JS
498
- - Loop safety:
499
- - Global `routing.max_loops` per scope to prevent livelock
500
- - Per‑step attempt counters; forEach items have isolated counters
427
+ Transform step output before passing to dependents:
501
428
 
502
- Example (retry + goto on failure):
503
429
  ```yaml
504
- version: "2.0"
505
- routing:
506
- max_loops: 5
507
430
  steps:
508
- setup: { type: command, exec: "echo setup" }
509
- build:
431
+ fetch:
510
432
  type: command
511
- depends_on: [setup]
512
- exec: |
513
- test -f .ok || (echo first try fails >&2; touch .ok; exit 1)
514
- echo ok
515
- on_fail:
516
- goto: setup
517
- retry: { max: 1, backoff: { mode: exponential, delay_ms: 400 } }
433
+ exec: 'node -e "console.log(JSON.stringify({items:[1,2,3]}))"'
434
+ transform_js: |
435
+ return output.items.filter(i => i > 1);
518
436
  ```
519
437
 
520
- Example (on_success jump‑back once):
438
+ ### Dynamic Routing with JavaScript
439
+
521
440
  ```yaml
522
441
  steps:
523
- unit: { type: command, exec: "echo unit" }
524
- build:
442
+ check:
525
443
  type: command
526
- depends_on: [unit]
527
- exec: "echo build"
528
- on_success:
529
- run: [notify]
444
+ exec: npm test
445
+ on_fail:
530
446
  goto_js: |
531
- // Jump back only on first success
532
- return attempt === 1 ? 'unit' : null;
533
- notify: { type: command, exec: "echo notify" }
447
+ if (attempt > 3) return null; // Give up
448
+ return 'fix-and-retry'; // Jump to remediation
534
449
  ```
535
450
 
536
- Learn more: [docs/failure-routing.md](docs/failure-routing.md)
537
-
538
- ## 🤖 Claude Code Provider
451
+ Prompts can live in external files with full Liquid variable access:
539
452
 
540
- Use the Claude Code SDK as a provider for deeper analysis.
541
-
542
- Example:
543
453
  ```yaml
544
454
  steps:
545
- claude-review:
546
- type: claude-code
547
- prompt: "Analyze code complexity"
455
+ overview:
456
+ type: ai
457
+ schema: code-review
458
+ prompt: ./prompts/overview.liquid
548
459
  ```
549
460
 
550
- Learn more: [docs/claude-code.md](docs/claude-code.md)
551
-
552
- ## 🔄 AI Session Reuse
461
+ Learn more: [docs/liquid-templates.md](docs/liquid-templates.md) · [docs/schema-templates.md](docs/schema-templates.md)
553
462
 
554
- Reuse conversation context between dependent AI checks for smarter follow‑ups.
463
+ ## 🔇 Suppressing Warnings
555
464
 
556
- **Two modes available:**
557
- - **`clone` (default)**: Independent copy of history for parallel follow-ups
558
- - **`append`**: Shared conversation thread for sequential multi-turn dialogue
465
+ Suppress a specific issue by adding a nearby `visor-disable` comment:
559
466
 
560
- Example:
561
- ```yaml
562
- steps:
563
- security: { type: ai }
564
- remediation:
565
- type: ai
566
- depends_on: [security]
567
- reuse_ai_session: true # Clones history by default
568
- verify:
569
- type: ai
570
- depends_on: [remediation]
571
- reuse_ai_session: true
572
- session_mode: append # Shares history for full conversation
467
+ ```js
468
+ const testPassword = "demo123"; // visor-disable
573
469
  ```
574
470
 
575
- You can also reuse the **same check’s** session when it loops back to itself, using:
576
-
577
- - `reuse_ai_session: "self"` with `session_mode: append`
578
-
579
- See the standalone example at `examples/session-reuse-self.yaml` and the detailed guide in [docs/advanced-ai.md](docs/advanced-ai.md).
580
-
581
- Learn more: [docs/advanced-ai.md](docs/advanced-ai.md)
471
+ Learn more: [docs/suppressions.md](docs/suppressions.md)
582
472
 
583
- ## 📋 Schema-Template System
473
+ ## 🧪 Testing Framework
584
474
 
585
- Schemas validate outputs; templates render GitHub‑friendly comments.
475
+ Write and run integration tests for your Visor config in YAML:
586
476
 
587
- Example:
588
477
  ```yaml
589
- steps:
590
- security:
591
- type: ai
592
- schema: code-review
593
- prompt: "Return JSON matching code-review schema"
478
+ # .visor.tests.yaml
479
+ tests:
480
+ - name: "Security check finds issues"
481
+ config: .visor.yaml
482
+ steps:
483
+ security:
484
+ mock_output: '{"issues": [{"severity": "high"}]}'
485
+ assertions:
486
+ - step: security
487
+ called: { exactly: 1 }
488
+ - step: security
489
+ output_contains: "high"
594
490
  ```
595
491
 
596
- Learn more: [docs/schema-templates.md](docs/schema-templates.md)
597
-
598
- ## 🎯 Enhanced Prompts
599
-
600
- Write prompts inline or in files; Liquid variables provide PR context.
601
-
602
- Example:
603
- ```yaml
604
- steps:
605
- overview:
606
- type: ai
607
- prompt: ./prompts/overview.liquid
492
+ ```bash
493
+ visor test --progress compact # Run tests
494
+ visor test --list # List test cases
495
+ visor test --only "Security*" # Filter tests
496
+ visor test --bail # Stop on first failure
608
497
  ```
609
498
 
610
- Learn more: [docs/liquid-templates.md](docs/liquid-templates.md)
499
+ Docs: [Getting started](docs/testing/getting-started.md) · [DSL reference](docs/testing/dsl-reference.md) · [Fixtures & mocks](docs/testing/fixtures-and-mocks.md) · [Assertions](docs/testing/assertions.md) · [Cookbook](docs/testing/cookbook.md)
611
500
 
612
501
  ## 📦 SDK (Programmatic Usage)
613
502
 
614
- Run Visor programmatically from Node.js without shelling out. The SDK is a thin façade over the existing engine.
615
-
616
- **Install:**
617
- ```bash
618
- npm i -D @probelabs/visor
619
- ```
503
+ Run Visor programmatically from Node.js:
620
504
 
621
- **ESM Example:**
622
505
  ```ts
623
506
  import { loadConfig, runChecks } from '@probelabs/visor/sdk';
624
507
 
625
- const config = await loadConfig();
508
+ const config = await loadConfig('.visor.yaml');
626
509
  const result = await runChecks({
627
510
  config,
628
511
  checks: Object.keys(config.checks || {}),
629
512
  output: { format: 'json' },
630
513
  });
631
- console.log('Total issues:', result.reviewSummary.issues?.length ?? 0);
514
+ console.log('Issues:', result.reviewSummary.issues?.length ?? 0);
632
515
  ```
633
516
 
634
- **CommonJS Example:**
635
- ```js
636
- const { loadConfig, runChecks } = require('@probelabs/visor/sdk');
637
- (async () => {
638
- const config = await loadConfig();
639
- const result = await runChecks({
640
- config,
641
- checks: Object.keys(config.checks || {}),
642
- output: { format: 'json' }
643
- });
644
- console.log('Total issues:', result.reviewSummary.issues?.length ?? 0);
645
- })();
646
- ```
647
-
648
- **Key Functions:**
649
- - `loadConfig(configPath?: string)` — Load Visor config
650
- - `resolveChecks(checkIds, config)` — Expand check IDs with dependencies
651
- - `runChecks(options)` — Run checks programmatically
652
-
653
517
  Learn more: [docs/sdk.md](docs/sdk.md)
654
518
 
655
- ## 🔍 Debugging
519
+ ## 🔧 Configuration
656
520
 
657
- Comprehensive debugging tools help troubleshoot configurations and data flows:
521
+ ### Config Loading Order
522
+ 1. CLI `--config` flag
523
+ 2. `.visor.yaml` in project root
524
+ 3. Built-in defaults
658
525
 
659
- ### Running Locally
526
+ ### Extending Configs
660
527
 
661
- ```bash
662
- # Basic CLI run
663
- visor --config .visor.yaml --check all
528
+ ```yaml
529
+ extends:
530
+ - default
531
+ - ./team-standards.yaml
532
+ - https://raw.githubusercontent.com/org/policies/main/base.yaml
533
+ ```
664
534
 
665
- # TUI mode - interactive chat interface for human-input workflows
666
- visor --tui --config ./examples/calculator-config.yaml
535
+ ### Dynamic Config Reloading
667
536
 
668
- # Debug server - web UI for stepping through execution
669
- visor --debug-server --debug-port 3456
537
+ Long-running modes (Slack, HTTP) support live config reload:
670
538
 
671
- # Combine options for full visibility
672
- visor --tui --config .visor.yaml --debug
539
+ ```bash
540
+ visor --slack --config .visor.yaml --watch # Auto-reload on file change
541
+ visor config snapshots # List config versions
542
+ visor config diff 1 2 # Diff two snapshots
673
543
  ```
674
544
 
675
- **TUI Mode Features:**
676
- - Chat-style interface with persistent input bar
677
- - Press `Tab` to switch between Chat and Logs tabs
678
- - Re-run workflows by typing new messages after completion
679
- - Press `q` to exit when done
545
+ ### Key Config Options
680
546
 
681
- ### Quick Debugging Tips
682
-
683
- **Use `log()` in JavaScript expressions:**
684
547
  ```yaml
548
+ version: "1.0"
549
+ max_parallelism: 3 # Concurrent steps
550
+ max_ai_concurrency: 3 # Concurrent AI API calls
551
+ routing:
552
+ max_loops: 10 # Loop safety limit
553
+
554
+ http_server:
555
+ enabled: true
556
+ port: 8080
557
+ auth: { bearer_token: "${WEBHOOK_SECRET}" }
558
+
559
+ telemetry:
560
+ enabled: true
561
+ sink: otlp # or: file, console
562
+
685
563
  steps:
686
- conditional-check:
687
- if: |
688
- log("Outputs:", outputs);
689
- outputs["fetch-data"]?.status === "ready"
690
- transform_js: |
691
- // `output` is auto‑parsed JSON when possible; no JSON.parse needed
692
- log("Raw data:", output);
693
- output
564
+ # ... your pipeline
565
+ ```
566
+
567
+ Learn more: [docs/configuration.md](docs/configuration.md)
568
+
569
+ ## 👀 Observability
570
+
571
+ ### Output Formats
572
+
573
+ ```bash
574
+ visor --output table # Terminal-friendly (default)
575
+ visor --output json --output-file results.json
576
+ visor --output sarif --output-file results.sarif
577
+ visor --output markdown
694
578
  ```
695
579
 
696
- **Use `json` filter in Liquid templates:**
580
+ ### OpenTelemetry Tracing
581
+
697
582
  ```yaml
698
- steps:
699
- debug-check:
700
- type: logger
701
- message: |
702
- Outputs: {{ outputs | json }}
703
- PR: {{ pr | json }}
583
+ telemetry:
584
+ enabled: true
585
+ sink: otlp
704
586
  ```
705
587
 
706
- **Enable debug mode:**
707
588
  ```bash
708
- visor --check all --debug
589
+ OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://localhost:4318/v1/traces visor --check all
709
590
  ```
710
591
 
711
- Learn more: [docs/debugging.md](docs/debugging.md)
592
+ Span hierarchy: `visor.run` → `engine.state.*` → `visor.check.*` → `visor.foreach.item`
712
593
 
713
- ## 🔧 Advanced Configuration
594
+ ### Debug Tools
714
595
 
715
- Extend shared configs and override per‑repo settings.
596
+ ```bash
597
+ visor --debug # Verbose logging
598
+ visor --debug-server --debug-port 3456 # Live web visualizer
599
+ ```
716
600
 
717
- Example:
601
+ **Quick debugging tips:**
602
+
603
+ Use `log()` in JavaScript expressions (`if`, `fail_if`, `transform_js`):
718
604
  ```yaml
719
- extends:
720
- - default
721
- - ./team-standards.yaml
605
+ if: |
606
+ log("Outputs:", outputs);
607
+ outputs["fetch-data"]?.status === "ready"
722
608
  ```
723
609
 
724
- Learn more: [docs/configuration.md](docs/configuration.md)
610
+ Use the `json` filter in Liquid to inspect objects:
611
+ ```yaml
612
+ type: logger
613
+ message: "Outputs: {{ outputs | json }}"
614
+ ```
725
615
 
726
- ## 🌐 HTTP Integration & Scheduling
616
+ **TUI mode** (`visor --tui`): Press `Tab` to switch between Chat and Logs tabs, `q` to exit.
727
617
 
728
- Receive webhooks, call APIs, and schedule checks.
618
+ Learn more: [docs/observability.md](docs/observability.md) · [docs/debugging.md](docs/debugging.md) · [docs/debug-visualizer.md](docs/debug-visualizer.md)
729
619
 
730
- Examples:
731
- ```yaml
732
- http_server: { enabled: true, port: 8080 }
733
- steps:
734
- nightly: { type: ai, schedule: "0 2 * * *" }
735
- ```
620
+ ## 🔐 Security
736
621
 
737
- Learn more: [docs/http.md](docs/http.md)
622
+ - **GitHub App support** for scoped, auditable access
623
+ - **Remote extends allowlist** to control external config sources
624
+ - **MCP method filtering** — allow/deny lists with wildcards
625
+ - **Bash allow/deny patterns** for AI-driven command execution
626
+ - **Docker & process sandboxes** for isolated step execution
627
+ - **Author permissions** — `hasMinPermission()`, `isMember()`, etc. for role-based logic
628
+ - **Environment filtering** — control which env vars steps can access
738
629
 
739
- ## 🔧 Pluggable Architecture
630
+ ```bash
631
+ visor --no-remote-extends
632
+ visor --allowed-remote-patterns "https://raw.githubusercontent.com/myorg/"
633
+ ```
740
634
 
741
- Mix providers (`ai`, `mcp`, `http`, `http_client`, `log`, `command`, `script`, `github`, `claude-code`) or add your own.
635
+ Learn more: [docs/security.md](docs/security.md) · [docs/author-permissions.md](docs/author-permissions.md)
742
636
 
743
- - **Command Provider**: Execute shell commands with templating and security - [docs/command-provider.md](docs/command-provider.md)
744
- - **Script Provider**: Run JavaScript in a secure sandbox - [docs/script.md](docs/script.md)
745
- - **MCP Provider**: Call MCP tools directly via stdio, SSE, or HTTP transports - [docs/mcp-provider.md](docs/mcp-provider.md)
746
- - **MCP Tools for AI**: Enhance AI providers with MCP context - [docs/mcp.md](docs/mcp.md)
747
- - **Custom Providers**: Build your own providers - [docs/pluggable.md](docs/pluggable.md)
637
+ ## 🏢 Enterprise Policy Engine (EE)
748
638
 
749
- ## 🎯 GitHub Action Reference
639
+ > **Enterprise Edition.** Requires a Visor EE license. Contact **hello@probelabs.com**.
750
640
 
751
- Common inputs include `max-parallelism`, `fail-fast`, and `config-path`.
641
+ OPA-based policy enforcement for gating checks, MCP tools, and AI capabilities:
752
642
 
753
- Example:
754
643
  ```yaml
755
- - uses: probelabs/visor@v1
756
- with:
757
- max-parallelism: 5
644
+ policy:
645
+ engine: local
646
+ rules: ./policies/
647
+ fallback: deny
648
+ roles:
649
+ admin: { author_association: [OWNER] }
650
+ developer: { author_association: [MEMBER, COLLABORATOR] }
758
651
  ```
759
652
 
760
- Learn more: [docs/action-reference.md](docs/action-reference.md)
653
+ Learn more: [docs/enterprise-policy.md](docs/enterprise-policy.md)
761
654
 
762
- ## 📊 Output Formats
655
+ ## 📚 Further Reading
763
656
 
764
- Emit `table`, `json`, `markdown`, or `sarif`.
657
+ **Guides:**
658
+ [CLI commands](docs/commands.md) · [Configuration](docs/configuration.md) · [AI config](docs/ai-configuration.md) · [Dependencies](docs/dependencies.md) · [forEach propagation](docs/foreach-dependency-propagation.md) · [Failure routing](docs/failure-routing.md) · [Liquid templates](docs/liquid-templates.md) · [Schema-template system](docs/schema-templates.md) · [Fail conditions](docs/fail-if.md) · [Timeouts](docs/timeouts.md) · [Execution limits](docs/limits.md) · [Output formats](docs/output-formats.md) · [Output formatting](docs/output-formatting.md) · [HTTP integration](docs/http.md) · [Scheduler](docs/scheduler.md)
765
659
 
766
- Example:
767
- ```bash
768
- visor --check security --output json
769
- ```
660
+ **Providers:**
661
+ [Command](docs/command-provider.md) · [Script](docs/script.md) · [MCP](docs/mcp-provider.md) · [MCP tools for AI](docs/mcp.md) · [Claude Code](docs/claude-code.md) · [GitHub ops](docs/github-ops.md) · [Custom providers](docs/pluggable.md)
770
662
 
771
- Learn more: [docs/output-formats.md](docs/output-formats.md)
663
+ **Operations:**
664
+ [GitHub Action reference](docs/action-reference.md) · [Security](docs/security.md) · [Performance](docs/performance.md) · [Observability](docs/observability.md) · [Debugging](docs/debugging.md) · [Debug visualizer](docs/debug-visualizer.md) · [Troubleshooting](docs/troubleshooting.md) · [Suppressions](docs/suppressions.md) · [GitHub checks](docs/GITHUB_CHECKS.md)
772
665
 
773
- ## 🤝 Contributing
666
+ **Architecture:**
667
+ [Failure conditions schema](docs/failure-conditions-schema.md) · [Failure conditions implementation](docs/failure-conditions-implementation.md)
774
668
 
775
- Learn more: [CONTRIBUTING.md](CONTRIBUTING.md)
669
+ **Testing:**
670
+ [Getting started](docs/testing/getting-started.md) · [DSL reference](docs/testing/dsl-reference.md) · [Flows](docs/testing/flows.md) · [Fixtures & mocks](docs/testing/fixtures-and-mocks.md) · [Assertions](docs/testing/assertions.md) · [Cookbook](docs/testing/cookbook.md) · [CLI & reporters](docs/testing/cli.md) · [CI integration](docs/testing/ci.md) · [Troubleshooting](docs/testing/troubleshooting.md)
776
671
 
777
- ## 📚 Further Reading
672
+ **Recipes & examples:**
673
+ [Recipes](docs/recipes.md) · [Dev playbook](docs/dev-playbook.md) · [Tag filtering](docs/tag-filtering.md) · [Author permissions](docs/author-permissions.md) · [Session reuse](docs/advanced-ai.md)
778
674
 
779
- - Failure conditions schema: [docs/failure-conditions-schema.md](docs/failure-conditions-schema.md)
780
- - Failure conditions implementation notes: [docs/failure-conditions-implementation.md](docs/failure-conditions-implementation.md)
781
- - Recipes and practical examples: [docs/recipes.md](docs/recipes.md)
782
- - ForEach outputs and precedence (outputs vs outputs_raw vs history): [docs/foreach-dependency-propagation.md](docs/foreach-dependency-propagation.md)
783
- - Failure routing and on_finish aggregation (with outputs_raw in routing): [docs/failure-routing.md](docs/failure-routing.md)
784
- - Example config using outputs_raw: examples/outputs-raw-basic.yaml
675
+ ## 🤝 Contributing
676
+
677
+ Learn more: [CONTRIBUTING.md](CONTRIBUTING.md)
785
678
 
786
679
  ## 📄 License
787
680
 
@@ -792,32 +685,3 @@ MIT License — see [LICENSE](LICENSE)
792
685
  <div align="center">
793
686
  Made with ❤️ by <a href="https://probelabs.com">Probe Labs</a>
794
687
  </div>
795
- ## 🧰 GitHub Provider
796
-
797
- Use the native GitHub provider for safe labels and comments without invoking the `gh` CLI.
798
-
799
- Example — apply overview‑derived labels to a PR:
800
-
801
- ```yaml
802
- steps:
803
- apply-overview-labels:
804
- type: github
805
- op: labels.add
806
- values:
807
- - "{{ outputs.overview.tags.label | default: '' | safe_label }}"
808
- - "{{ outputs.overview.tags['review-effort'] | default: '' | prepend: 'review/effort:' | safe_label }}"
809
- value_js: |
810
- return values.filter(v => typeof v === 'string' && v.trim().length > 0);
811
- ```
812
-
813
- See docs: docs/github-ops.md
814
- ## Integration Tests
815
-
816
- Visor ships a YAML‑native integration test runner so you can describe user flows, mocks, and assertions alongside your config.
817
-
818
- - Start here: docs/testing/getting-started.md
819
- - CLI details: docs/testing/cli.md
820
- - Fixtures and mocks: docs/testing/fixtures-and-mocks.md
821
- - Assertions reference: docs/testing/assertions.md
822
-
823
- Example suite: defaults/.visor.tests.yaml