@probelabs/visor 0.1.130 → 0.1.131
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/README.md +7 -0
- package/defaults/visor.yaml +5 -2
- package/dist/ai-review-service.d.ts +2 -0
- package/dist/ai-review-service.d.ts.map +1 -1
- package/dist/cli-main.d.ts.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/config/cli-handler.d.ts +5 -0
- package/dist/config/cli-handler.d.ts.map +1 -0
- package/dist/config/config-reloader.d.ts +24 -0
- package/dist/config/config-reloader.d.ts.map +1 -0
- package/dist/config/config-snapshot-store.d.ts +21 -0
- package/dist/config/config-snapshot-store.d.ts.map +1 -0
- package/dist/config/config-watcher.d.ts +19 -0
- package/dist/config/config-watcher.d.ts.map +1 -0
- package/dist/config/types.d.ts +16 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/defaults/visor.yaml +5 -2
- package/dist/docs/ai-configuration.md +139 -0
- package/dist/docs/ai-custom-tools.md +30 -0
- package/dist/docs/capacity-planning.md +359 -0
- package/dist/docs/commands.md +35 -0
- package/dist/docs/database-operations.md +487 -0
- package/dist/docs/index.md +6 -1
- package/dist/docs/licensing.md +372 -0
- package/dist/docs/production-deployment.md +583 -0
- package/dist/examples/ai-with-bash.yaml +17 -0
- package/dist/generated/config-schema.d.ts +4 -0
- package/dist/generated/config-schema.d.ts.map +1 -1
- package/dist/index.js +9945 -10907
- package/dist/liquid-extensions.d.ts +7 -0
- package/dist/liquid-extensions.d.ts.map +1 -1
- package/dist/output/traces/{run-2026-02-11T16-20-59-999Z.ndjson → run-2026-02-15T19-14-20-379Z.ndjson} +84 -84
- package/dist/{traces/run-2026-02-11T16-21-47-711Z.ndjson → output/traces/run-2026-02-15T19-15-09-410Z.ndjson} +1019 -1019
- package/dist/providers/ai-check-provider.d.ts +5 -0
- 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/workflow-check-provider.d.ts.map +1 -1
- package/dist/scheduler/schedule-tool.d.ts.map +1 -1
- package/dist/sdk/{check-provider-registry-PANIXYRB.mjs → check-provider-registry-AAPPJ4CP.mjs} +7 -7
- package/dist/sdk/{check-provider-registry-M3Y6JMTW.mjs → check-provider-registry-S7BMQ2FC.mjs} +7 -7
- package/dist/sdk/check-provider-registry-ZOLEYDKM.mjs +28 -0
- package/dist/sdk/{chunk-VMLORODQ.mjs → chunk-2GCSK3PD.mjs} +4 -4
- package/dist/sdk/{chunk-EUUAQBTW.mjs → chunk-6ZZ4DPAA.mjs} +240 -48
- package/dist/sdk/chunk-6ZZ4DPAA.mjs.map +1 -0
- package/dist/sdk/{chunk-HOKQOO3G.mjs → chunk-EBTD2D4L.mjs} +2 -2
- package/dist/sdk/chunk-LDFUW34H.mjs +39912 -0
- package/dist/sdk/chunk-LDFUW34H.mjs.map +1 -0
- package/dist/sdk/{chunk-UCNT3PDT.mjs → chunk-LQ5B4T6L.mjs} +5 -1
- package/dist/sdk/chunk-LQ5B4T6L.mjs.map +1 -0
- package/dist/sdk/{chunk-S6CD7GFM.mjs → chunk-MQ57AB4U.mjs} +211 -35
- package/dist/sdk/chunk-MQ57AB4U.mjs.map +1 -0
- package/dist/sdk/chunk-N4I6ZDCJ.mjs +436 -0
- package/dist/sdk/chunk-N4I6ZDCJ.mjs.map +1 -0
- package/dist/sdk/chunk-OMFPM576.mjs +739 -0
- package/dist/sdk/chunk-OMFPM576.mjs.map +1 -0
- package/dist/sdk/chunk-RI77TA6V.mjs +436 -0
- package/dist/sdk/chunk-RI77TA6V.mjs.map +1 -0
- package/dist/sdk/chunk-VO4N6TEL.mjs +1502 -0
- package/dist/sdk/chunk-VO4N6TEL.mjs.map +1 -0
- package/dist/sdk/{chunk-V2IV3ILA.mjs → chunk-XJQKTK6V.mjs} +31 -5
- package/dist/sdk/chunk-XJQKTK6V.mjs.map +1 -0
- package/dist/sdk/{config-OGOS4ZU4.mjs → config-4EG7IQIU.mjs} +2 -2
- package/dist/sdk/{failure-condition-evaluator-HC3M5377.mjs → failure-condition-evaluator-GLHZZF47.mjs} +3 -3
- package/dist/sdk/failure-condition-evaluator-KN55WXRO.mjs +17 -0
- package/dist/sdk/{github-frontend-E2KJSC3Y.mjs → github-frontend-F4TE2JY7.mjs} +3 -3
- package/dist/sdk/github-frontend-HCOKL53D.mjs +1356 -0
- package/dist/sdk/github-frontend-HCOKL53D.mjs.map +1 -0
- package/dist/sdk/{host-EE6EJ2FM.mjs → host-SAT6RHDX.mjs} +2 -2
- package/dist/sdk/host-VA3ET7N6.mjs +63 -0
- package/dist/sdk/host-VA3ET7N6.mjs.map +1 -0
- package/dist/sdk/{liquid-extensions-E4EUOCES.mjs → liquid-extensions-YDIIH33Q.mjs} +2 -2
- package/dist/sdk/{routing-OZQWAGAI.mjs → routing-KFYQGOYU.mjs} +5 -5
- package/dist/sdk/routing-OXQKETSA.mjs +25 -0
- package/dist/sdk/{schedule-tool-handler-IEB2VS7O.mjs → schedule-tool-handler-G353DHS6.mjs} +7 -7
- package/dist/sdk/{schedule-tool-handler-B7TMSG6A.mjs → schedule-tool-handler-OQF57URO.mjs} +7 -7
- package/dist/sdk/schedule-tool-handler-PJVKWSYX.mjs +38 -0
- package/dist/sdk/schedule-tool-handler-PJVKWSYX.mjs.map +1 -0
- package/dist/sdk/sdk.d.mts +15 -0
- package/dist/sdk/sdk.d.ts +15 -0
- package/dist/sdk/sdk.js +621 -183
- package/dist/sdk/sdk.js.map +1 -1
- package/dist/sdk/sdk.mjs +6 -6
- package/dist/sdk/{trace-helpers-PP3YHTAM.mjs → trace-helpers-LOPBHYYX.mjs} +4 -2
- package/dist/sdk/trace-helpers-LOPBHYYX.mjs.map +1 -0
- package/dist/sdk/trace-helpers-R2ETIEC2.mjs +25 -0
- package/dist/sdk/trace-helpers-R2ETIEC2.mjs.map +1 -0
- package/dist/sdk/{workflow-check-provider-2ET3SFZH.mjs → workflow-check-provider-57KAR4Y4.mjs} +7 -7
- package/dist/sdk/workflow-check-provider-57KAR4Y4.mjs.map +1 -0
- package/dist/sdk/{workflow-check-provider-HB4XTD4Z.mjs → workflow-check-provider-LRWD52WN.mjs} +7 -7
- package/dist/sdk/workflow-check-provider-LRWD52WN.mjs.map +1 -0
- package/dist/sdk/workflow-check-provider-N2DRFQDB.mjs +28 -0
- package/dist/sdk/workflow-check-provider-N2DRFQDB.mjs.map +1 -0
- package/dist/slack/socket-runner.d.ts.map +1 -1
- package/dist/state-machine/context/build-engine-context.d.ts.map +1 -1
- package/dist/state-machine/runner.d.ts.map +1 -1
- package/dist/state-machine/states/completed.d.ts.map +1 -1
- package/dist/telemetry/trace-helpers.d.ts +5 -0
- package/dist/telemetry/trace-helpers.d.ts.map +1 -1
- package/dist/test-runner/evaluators.d.ts.map +1 -1
- package/dist/test-runner/index.d.ts +7 -0
- package/dist/test-runner/index.d.ts.map +1 -1
- package/dist/test-runner/validator.d.ts.map +1 -1
- package/dist/traces/{run-2026-02-11T16-20-59-999Z.ndjson → run-2026-02-15T19-14-20-379Z.ndjson} +84 -84
- package/dist/{output/traces/run-2026-02-11T16-21-47-711Z.ndjson → traces/run-2026-02-15T19-15-09-410Z.ndjson} +1019 -1019
- package/dist/tui/chat-runner.d.ts.map +1 -1
- package/dist/types/cli.d.ts +2 -0
- package/dist/types/cli.d.ts.map +1 -1
- package/dist/types/config.d.ts +15 -0
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/engine.d.ts +2 -0
- package/dist/types/engine.d.ts.map +1 -1
- package/package.json +3 -3
- package/defaults/.visor.yaml +0 -420
- package/dist/sdk/chunk-EUUAQBTW.mjs.map +0 -1
- package/dist/sdk/chunk-S6CD7GFM.mjs.map +0 -1
- package/dist/sdk/chunk-UCNT3PDT.mjs.map +0 -1
- package/dist/sdk/chunk-V2IV3ILA.mjs.map +0 -1
- package/dist/sdk/chunk-YJRBN3XS.mjs +0 -217
- package/dist/sdk/chunk-YJRBN3XS.mjs.map +0 -1
- /package/dist/sdk/{check-provider-registry-M3Y6JMTW.mjs.map → check-provider-registry-AAPPJ4CP.mjs.map} +0 -0
- /package/dist/sdk/{check-provider-registry-PANIXYRB.mjs.map → check-provider-registry-S7BMQ2FC.mjs.map} +0 -0
- /package/dist/sdk/{config-OGOS4ZU4.mjs.map → check-provider-registry-ZOLEYDKM.mjs.map} +0 -0
- /package/dist/sdk/{chunk-VMLORODQ.mjs.map → chunk-2GCSK3PD.mjs.map} +0 -0
- /package/dist/sdk/{chunk-HOKQOO3G.mjs.map → chunk-EBTD2D4L.mjs.map} +0 -0
- /package/dist/sdk/{failure-condition-evaluator-HC3M5377.mjs.map → config-4EG7IQIU.mjs.map} +0 -0
- /package/dist/sdk/{liquid-extensions-E4EUOCES.mjs.map → failure-condition-evaluator-GLHZZF47.mjs.map} +0 -0
- /package/dist/sdk/{routing-OZQWAGAI.mjs.map → failure-condition-evaluator-KN55WXRO.mjs.map} +0 -0
- /package/dist/sdk/{github-frontend-E2KJSC3Y.mjs.map → github-frontend-F4TE2JY7.mjs.map} +0 -0
- /package/dist/sdk/{host-EE6EJ2FM.mjs.map → host-SAT6RHDX.mjs.map} +0 -0
- /package/dist/sdk/{schedule-tool-handler-B7TMSG6A.mjs.map → liquid-extensions-YDIIH33Q.mjs.map} +0 -0
- /package/dist/sdk/{schedule-tool-handler-IEB2VS7O.mjs.map → routing-KFYQGOYU.mjs.map} +0 -0
- /package/dist/sdk/{trace-helpers-PP3YHTAM.mjs.map → routing-OXQKETSA.mjs.map} +0 -0
- /package/dist/sdk/{workflow-check-provider-2ET3SFZH.mjs.map → schedule-tool-handler-G353DHS6.mjs.map} +0 -0
- /package/dist/sdk/{workflow-check-provider-HB4XTD4Z.mjs.map → schedule-tool-handler-OQF57URO.mjs.map} +0 -0
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
# Capacity Planning and Sizing
|
|
2
|
+
|
|
3
|
+
This guide helps you size Visor deployments for different workloads, from single-developer setups to large-scale enterprise deployments.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Table of Contents
|
|
8
|
+
|
|
9
|
+
- [Resource Profiles](#resource-profiles)
|
|
10
|
+
- [Deployment Tiers](#deployment-tiers)
|
|
11
|
+
- [Component Sizing](#component-sizing)
|
|
12
|
+
- [Visor Instances](#visor-instances)
|
|
13
|
+
- [Database](#database)
|
|
14
|
+
- [AI Provider Costs](#ai-provider-costs)
|
|
15
|
+
- [Scaling Guidelines](#scaling-guidelines)
|
|
16
|
+
- [Bottleneck Analysis](#bottleneck-analysis)
|
|
17
|
+
- [Cloud Cost Estimates](#cloud-cost-estimates)
|
|
18
|
+
- [Load Testing](#load-testing)
|
|
19
|
+
- [Monitoring for Scale](#monitoring-for-scale)
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Resource Profiles
|
|
24
|
+
|
|
25
|
+
Visor's resource consumption depends primarily on:
|
|
26
|
+
|
|
27
|
+
1. **Number of concurrent checks**: Each check consumes a thread and memory for provider execution.
|
|
28
|
+
2. **AI provider usage**: AI checks send/receive large payloads (code diffs, prompts, responses).
|
|
29
|
+
3. **Sandbox usage**: Docker-based sandboxes consume additional CPU/memory per container.
|
|
30
|
+
4. **Scheduler load**: Number of active schedules and execution frequency.
|
|
31
|
+
|
|
32
|
+
### Per-Check Resource Footprint
|
|
33
|
+
|
|
34
|
+
| Check Type | CPU (avg) | Memory (avg) | Network | Duration |
|
|
35
|
+
|-----------|----------|-------------|---------|----------|
|
|
36
|
+
| `command` | 50m | 20MB | Minimal | 1-30s |
|
|
37
|
+
| `script` | 50m | 30MB | None | < 1s |
|
|
38
|
+
| `ai` (Gemini) | 10m | 50MB | Moderate | 5-30s |
|
|
39
|
+
| `ai` (Claude) | 10m | 50MB | Moderate | 10-60s |
|
|
40
|
+
| `claude-code` | 100m | 200MB | High | 30-300s |
|
|
41
|
+
| `mcp` | 50m | 50MB | Varies | 1-60s |
|
|
42
|
+
| `http` / `http_client` | 10m | 10MB | Low | 1-10s |
|
|
43
|
+
| Sandbox (Docker) | 250m+ | 256MB+ | Varies | 10-120s |
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Deployment Tiers
|
|
48
|
+
|
|
49
|
+
### Small (1-10 developers)
|
|
50
|
+
|
|
51
|
+
Single instance, SQLite, ephemeral runs.
|
|
52
|
+
|
|
53
|
+
| Component | Spec | Cost Estimate |
|
|
54
|
+
|-----------|------|---------------|
|
|
55
|
+
| Visor | 1 instance, 256MB RAM, 0.5 CPU | Free (CLI) or $5/mo (small VM) |
|
|
56
|
+
| Database | SQLite (local file) | $0 |
|
|
57
|
+
| AI Provider | ~100 reviews/month | $5-20/mo |
|
|
58
|
+
|
|
59
|
+
**Configuration:**
|
|
60
|
+
```yaml
|
|
61
|
+
max_parallelism: 3
|
|
62
|
+
scheduler:
|
|
63
|
+
storage:
|
|
64
|
+
driver: sqlite
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Medium (10-50 developers)
|
|
68
|
+
|
|
69
|
+
2-3 instances, PostgreSQL, Slack integration.
|
|
70
|
+
|
|
71
|
+
| Component | Spec | Cost Estimate |
|
|
72
|
+
|-----------|------|---------------|
|
|
73
|
+
| Visor | 2-3 instances, 512MB RAM, 1 CPU each | $30-80/mo |
|
|
74
|
+
| Database | PostgreSQL (small managed) | $15-30/mo |
|
|
75
|
+
| AI Provider | ~500-2000 reviews/month | $30-150/mo |
|
|
76
|
+
|
|
77
|
+
**Configuration:**
|
|
78
|
+
```yaml
|
|
79
|
+
max_parallelism: 5
|
|
80
|
+
scheduler:
|
|
81
|
+
storage:
|
|
82
|
+
driver: postgresql
|
|
83
|
+
connection:
|
|
84
|
+
pool:
|
|
85
|
+
min: 1
|
|
86
|
+
max: 5
|
|
87
|
+
ha:
|
|
88
|
+
enabled: true
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Large (50-500 developers)
|
|
92
|
+
|
|
93
|
+
5+ instances, PostgreSQL with PgBouncer, full observability.
|
|
94
|
+
|
|
95
|
+
| Component | Spec | Cost Estimate |
|
|
96
|
+
|-----------|------|---------------|
|
|
97
|
+
| Visor | 5+ instances, 1GB RAM, 2 CPU each | $150-400/mo |
|
|
98
|
+
| Database | PostgreSQL (medium managed + replica) | $50-200/mo |
|
|
99
|
+
| PgBouncer | 1 instance, 128MB RAM | $5-10/mo |
|
|
100
|
+
| AI Provider | ~5000-20000 reviews/month | $200-1500/mo |
|
|
101
|
+
| Observability | Jaeger/Grafana | $50-200/mo |
|
|
102
|
+
|
|
103
|
+
**Configuration:**
|
|
104
|
+
```yaml
|
|
105
|
+
max_parallelism: 10
|
|
106
|
+
scheduler:
|
|
107
|
+
storage:
|
|
108
|
+
driver: postgresql
|
|
109
|
+
connection:
|
|
110
|
+
pool:
|
|
111
|
+
min: 0
|
|
112
|
+
max: 3 # PgBouncer handles pooling
|
|
113
|
+
ha:
|
|
114
|
+
enabled: true
|
|
115
|
+
lock_ttl: 120
|
|
116
|
+
heartbeat_interval: 15
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## Component Sizing
|
|
122
|
+
|
|
123
|
+
### Visor Instances
|
|
124
|
+
|
|
125
|
+
| Metric | Formula | Example |
|
|
126
|
+
|--------|---------|---------|
|
|
127
|
+
| **Concurrent checks** | `instances * max_parallelism` | 3 * 5 = 15 concurrent |
|
|
128
|
+
| **Memory per instance** | `base (100MB) + checks * avg_per_check` | 100 + 5 * 50 = 350MB |
|
|
129
|
+
| **CPU per instance** | `0.25 base + checks * avg_cpu` | 0.25 + 5 * 0.05 = 0.5 cores |
|
|
130
|
+
|
|
131
|
+
**Recommended instance sizes:**
|
|
132
|
+
|
|
133
|
+
| Workload | vCPU | Memory | `max_parallelism` |
|
|
134
|
+
|----------|------|--------|-------------------|
|
|
135
|
+
| Light (CLI checks only) | 0.5 | 256MB | 3 |
|
|
136
|
+
| Medium (AI + Slack) | 1 | 512MB | 5 |
|
|
137
|
+
| Heavy (Claude Code + sandboxes) | 2 | 1GB | 5-10 |
|
|
138
|
+
| Sandbox-heavy | 4 | 2GB | 3-5 |
|
|
139
|
+
|
|
140
|
+
### Database
|
|
141
|
+
|
|
142
|
+
Visor's database footprint is small. The `schedules` table grows linearly with active schedules.
|
|
143
|
+
|
|
144
|
+
| Deployment | Rows (approx) | Disk | Recommended Instance |
|
|
145
|
+
|------------|--------------|------|---------------------|
|
|
146
|
+
| Small | < 100 | < 10MB | SQLite |
|
|
147
|
+
| Medium | 100-1000 | < 100MB | db.t3.micro (AWS) / B1ms (Azure) |
|
|
148
|
+
| Large | 1000-10000 | < 1GB | db.t3.small (AWS) / B2s (Azure) |
|
|
149
|
+
|
|
150
|
+
PostgreSQL memory recommendation: **256MB shared_buffers** is sufficient for all Visor workloads.
|
|
151
|
+
|
|
152
|
+
### AI Provider Costs
|
|
153
|
+
|
|
154
|
+
AI costs scale with the size of code diffs and prompt complexity.
|
|
155
|
+
|
|
156
|
+
| Provider | Model | Cost per 1K tokens (approx) | Avg tokens per review | Cost per review |
|
|
157
|
+
|----------|-------|-----------------------------|----------------------|-----------------|
|
|
158
|
+
| Gemini | gemini-2.0-flash | $0.0001 / $0.0004 | 5K-20K | $0.002-0.01 |
|
|
159
|
+
| Claude | claude-sonnet-4-5 | $0.003 / $0.015 | 5K-20K | $0.03-0.20 |
|
|
160
|
+
| Claude Code | claude-sonnet-4-5 | $0.003 / $0.015 | 10K-50K | $0.10-0.50 |
|
|
161
|
+
| OpenAI | gpt-4o | $0.0025 / $0.01 | 5K-20K | $0.03-0.15 |
|
|
162
|
+
|
|
163
|
+
**Cost optimization strategies:**
|
|
164
|
+
- Use Gemini Flash for high-volume, lower-stakes checks.
|
|
165
|
+
- Reserve Claude/GPT-4 for security and architecture reviews.
|
|
166
|
+
- Use `--tags` to run expensive checks only when needed.
|
|
167
|
+
- Set `max_tokens` in AI provider config to cap response size.
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## Scaling Guidelines
|
|
172
|
+
|
|
173
|
+
### When to Add Instances
|
|
174
|
+
|
|
175
|
+
| Signal | Action |
|
|
176
|
+
|--------|--------|
|
|
177
|
+
| Check queue backlog growing | Increase `max_parallelism` or add instances |
|
|
178
|
+
| Response times > 2x baseline | Add instances |
|
|
179
|
+
| Memory usage > 80% | Increase memory or reduce `max_parallelism` |
|
|
180
|
+
| Slack message response > 30s | Add instances for Slack mode |
|
|
181
|
+
|
|
182
|
+
### When to Upgrade Database
|
|
183
|
+
|
|
184
|
+
| Signal | Action |
|
|
185
|
+
|--------|--------|
|
|
186
|
+
| SQLite lock contention | Migrate to PostgreSQL |
|
|
187
|
+
| Multiple Visor instances needed | Migrate to PostgreSQL with HA |
|
|
188
|
+
| Connection pool exhaustion | Add PgBouncer |
|
|
189
|
+
| Query latency > 100ms | Check indexes, consider larger instance |
|
|
190
|
+
|
|
191
|
+
### Horizontal vs Vertical Scaling
|
|
192
|
+
|
|
193
|
+
| Dimension | Horizontal (more instances) | Vertical (bigger instance) |
|
|
194
|
+
|-----------|---------------------------|--------------------------|
|
|
195
|
+
| Best for | Slack throughput, HA | Heavy single checks, sandbox execution |
|
|
196
|
+
| Requires | PostgreSQL + HA mode | Nothing special |
|
|
197
|
+
| Limit | Slack API rate limits | Single-machine resources |
|
|
198
|
+
| Recommended | Yes, for production | Yes, up to 4 vCPU / 4GB |
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## Bottleneck Analysis
|
|
203
|
+
|
|
204
|
+
Common bottlenecks in order of likelihood:
|
|
205
|
+
|
|
206
|
+
### 1. AI Provider Latency (most common)
|
|
207
|
+
|
|
208
|
+
AI API calls (5-60s) dominate total execution time.
|
|
209
|
+
|
|
210
|
+
**Mitigation:**
|
|
211
|
+
- Increase `max_parallelism` to overlap AI calls.
|
|
212
|
+
- Use faster models (Gemini Flash) for non-critical checks.
|
|
213
|
+
- Use `timeout` per check to prevent hangs.
|
|
214
|
+
|
|
215
|
+
### 2. Sandbox Startup Time
|
|
216
|
+
|
|
217
|
+
Docker container creation adds 2-10s overhead per sandboxed check.
|
|
218
|
+
|
|
219
|
+
**Mitigation:**
|
|
220
|
+
- Pre-pull images on nodes.
|
|
221
|
+
- Use lightweight base images (`alpine`).
|
|
222
|
+
- Enable cache volumes to avoid re-installing dependencies.
|
|
223
|
+
|
|
224
|
+
### 3. Database Connection Pool
|
|
225
|
+
|
|
226
|
+
With many instances and high scheduler activity, connections can exhaust.
|
|
227
|
+
|
|
228
|
+
**Mitigation:**
|
|
229
|
+
- Deploy PgBouncer for connection multiplexing.
|
|
230
|
+
- Keep Visor `pool.max` low (3-5) when using PgBouncer.
|
|
231
|
+
- Monitor with `pg_stat_activity`.
|
|
232
|
+
|
|
233
|
+
### 4. Network / API Rate Limits
|
|
234
|
+
|
|
235
|
+
GitHub API (5000 req/hr), Slack API (tier-based).
|
|
236
|
+
|
|
237
|
+
**Mitigation:**
|
|
238
|
+
- Use GitHub App tokens (higher rate limits) instead of PATs.
|
|
239
|
+
- Batch operations where possible.
|
|
240
|
+
- Monitor rate limit headers.
|
|
241
|
+
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
## Cloud Cost Estimates
|
|
245
|
+
|
|
246
|
+
### AWS
|
|
247
|
+
|
|
248
|
+
| Component | Service | Spec | Monthly Cost |
|
|
249
|
+
|-----------|---------|------|-------------|
|
|
250
|
+
| Visor (2x) | ECS Fargate | 0.5 vCPU, 1GB | ~$30 |
|
|
251
|
+
| Database | RDS PostgreSQL | db.t3.micro | ~$15 |
|
|
252
|
+
| Secrets | Secrets Manager | 3 secrets | ~$1.20 |
|
|
253
|
+
| Monitoring | CloudWatch | Basic | ~$5 |
|
|
254
|
+
| **Total** | | | **~$51/mo** |
|
|
255
|
+
|
|
256
|
+
### Google Cloud
|
|
257
|
+
|
|
258
|
+
| Component | Service | Spec | Monthly Cost |
|
|
259
|
+
|-----------|---------|------|-------------|
|
|
260
|
+
| Visor (2x) | Cloud Run | 1 vCPU, 512MB | ~$25 |
|
|
261
|
+
| Database | Cloud SQL PostgreSQL | db-f1-micro | ~$10 |
|
|
262
|
+
| Secrets | Secret Manager | 3 secrets | ~$0.18 |
|
|
263
|
+
| Monitoring | Cloud Monitoring | Basic | Free |
|
|
264
|
+
| **Total** | | | **~$35/mo** |
|
|
265
|
+
|
|
266
|
+
### Azure
|
|
267
|
+
|
|
268
|
+
| Component | Service | Spec | Monthly Cost |
|
|
269
|
+
|-----------|---------|------|-------------|
|
|
270
|
+
| Visor (2x) | Container Instances | 1 vCPU, 1GB | ~$35 |
|
|
271
|
+
| Database | Azure Database for PostgreSQL | B1ms | ~$15 |
|
|
272
|
+
| Secrets | Key Vault | 3 secrets | ~$0.10 |
|
|
273
|
+
| Monitoring | Monitor | Basic | ~$5 |
|
|
274
|
+
| **Total** | | | **~$55/mo** |
|
|
275
|
+
|
|
276
|
+
*Costs are approximate and vary by region. AI provider costs are additional.*
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
## Load Testing
|
|
281
|
+
|
|
282
|
+
### Test Setup
|
|
283
|
+
|
|
284
|
+
Create a load-test configuration with synthetic checks:
|
|
285
|
+
|
|
286
|
+
```yaml
|
|
287
|
+
# load-test.visor.yaml
|
|
288
|
+
version: "1.0"
|
|
289
|
+
max_parallelism: 10
|
|
290
|
+
|
|
291
|
+
checks:
|
|
292
|
+
synthetic-fast:
|
|
293
|
+
type: command
|
|
294
|
+
command: "echo ok"
|
|
295
|
+
tags: [load-test]
|
|
296
|
+
|
|
297
|
+
synthetic-slow:
|
|
298
|
+
type: command
|
|
299
|
+
command: "sleep 2 && echo ok"
|
|
300
|
+
tags: [load-test]
|
|
301
|
+
|
|
302
|
+
synthetic-ai:
|
|
303
|
+
type: ai
|
|
304
|
+
prompt: "Say 'ok' in one word."
|
|
305
|
+
tags: [load-test]
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
### Running Load Tests
|
|
309
|
+
|
|
310
|
+
```bash
|
|
311
|
+
# Sequential: measure single-check latency
|
|
312
|
+
time visor --config load-test.visor.yaml --check all --tags load-test
|
|
313
|
+
|
|
314
|
+
# Parallel: measure throughput
|
|
315
|
+
for i in $(seq 1 20); do
|
|
316
|
+
visor --config load-test.visor.yaml --check all --tags load-test &
|
|
317
|
+
done
|
|
318
|
+
wait
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
### Key Metrics to Capture
|
|
322
|
+
|
|
323
|
+
- **P50/P95/P99 check duration**: Baseline for SLA.
|
|
324
|
+
- **Throughput**: Checks per minute at different parallelism levels.
|
|
325
|
+
- **Error rate**: Failed checks under load.
|
|
326
|
+
- **Memory growth**: Watch for leaks in long-running mode.
|
|
327
|
+
- **Database connections**: Peak concurrent connections.
|
|
328
|
+
|
|
329
|
+
---
|
|
330
|
+
|
|
331
|
+
## Monitoring for Scale
|
|
332
|
+
|
|
333
|
+
### Alerts to Configure
|
|
334
|
+
|
|
335
|
+
| Alert | Threshold | Action |
|
|
336
|
+
|-------|-----------|--------|
|
|
337
|
+
| Check error rate > 5% | 5min window | Investigate provider health |
|
|
338
|
+
| P95 latency > 120s | 5min window | Scale horizontally or reduce parallelism |
|
|
339
|
+
| Memory > 80% of limit | Sustained | Increase memory or reduce parallelism |
|
|
340
|
+
| DB connections > 80% of max | Sustained | Add PgBouncer or increase pool |
|
|
341
|
+
| Scheduler lock failures | Any | Check HA config, verify DB health |
|
|
342
|
+
| License expiring < 7 days | Daily check | Renew license |
|
|
343
|
+
|
|
344
|
+
### Grafana Dashboard Queries
|
|
345
|
+
|
|
346
|
+
If using OpenTelemetry with Grafana:
|
|
347
|
+
|
|
348
|
+
```promql
|
|
349
|
+
# Check execution rate
|
|
350
|
+
rate(visor_check_executions_total[5m])
|
|
351
|
+
|
|
352
|
+
# P95 check duration
|
|
353
|
+
histogram_quantile(0.95, rate(visor_check_duration_seconds_bucket[5m]))
|
|
354
|
+
|
|
355
|
+
# Active Visor instances (from heartbeat)
|
|
356
|
+
count(up{job="visor"})
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
See [Dashboards](./dashboards/README.md) for pre-built Grafana dashboards.
|
package/dist/docs/commands.md
CHANGED
|
@@ -78,6 +78,28 @@ visor build <path/to/agent.yaml> [options]
|
|
|
78
78
|
visor build agents/my-agent.yaml --message "Add error handling"
|
|
79
79
|
```
|
|
80
80
|
|
|
81
|
+
#### `visor config`
|
|
82
|
+
|
|
83
|
+
Manage configuration snapshots. Visor automatically snapshots resolved configuration at startup and on each reload, keeping the most recent 3 snapshots in `.visor/config.db`.
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
visor config <command> [options]
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
**Subcommands:**
|
|
90
|
+
- `snapshots` - List all configuration snapshots
|
|
91
|
+
- `show <id>` - Print the full YAML of a snapshot
|
|
92
|
+
- `diff <id_a> <id_b>` - Show unified diff between two snapshots
|
|
93
|
+
- `restore <id> --output <path>` - Write snapshot YAML to a file
|
|
94
|
+
|
|
95
|
+
**Examples:**
|
|
96
|
+
```bash
|
|
97
|
+
visor config snapshots # List saved snapshots
|
|
98
|
+
visor config show 1 # Print full YAML of snapshot 1
|
|
99
|
+
visor config diff 1 2 # Unified diff between snapshots
|
|
100
|
+
visor config restore 1 --output restored.yaml # Restore snapshot to file
|
|
101
|
+
```
|
|
102
|
+
|
|
81
103
|
#### `visor mcp-server`
|
|
82
104
|
|
|
83
105
|
Start Visor as an MCP (Model Context Protocol) server.
|
|
@@ -142,6 +164,9 @@ See [Tag Filtering](tag-filtering.md) for detailed tag filtering documentation.
|
|
|
142
164
|
- `--workspace-name <name>` - Workspace directory name
|
|
143
165
|
- `--workspace-project-name <name>` - Main project folder name inside workspace
|
|
144
166
|
|
|
167
|
+
#### Config Reloading
|
|
168
|
+
- `--watch` - Watch config file for changes and reload automatically (requires `--config`). Also reloads on `SIGUSR2` signal (non-Windows). Intended for long-running modes like `--slack`.
|
|
169
|
+
|
|
145
170
|
#### Other Options
|
|
146
171
|
- `--slack` - Enable Slack Socket Mode runner
|
|
147
172
|
- `--mode <mode>` - Run mode: `cli` (default) or `github-actions`
|
|
@@ -180,6 +205,16 @@ visor --tui
|
|
|
180
205
|
|
|
181
206
|
# Debug visualizer
|
|
182
207
|
visor --debug-server --debug-port 3456
|
|
208
|
+
|
|
209
|
+
# Slack mode with live config reloading
|
|
210
|
+
visor --slack --config .visor.yaml --watch
|
|
211
|
+
|
|
212
|
+
# Reload config at runtime via signal (non-Windows)
|
|
213
|
+
kill -USR2 <visor-pid>
|
|
214
|
+
|
|
215
|
+
# List config snapshots and diff changes
|
|
216
|
+
visor config snapshots
|
|
217
|
+
visor config diff 1 2
|
|
183
218
|
```
|
|
184
219
|
|
|
185
220
|
---
|