@probelabs/visor 0.1.74 → 0.1.76

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/sdk/sdk.js CHANGED
@@ -259,7 +259,7 @@ ${content}
259
259
  * Sleep utility
260
260
  */
261
261
  sleep(ms) {
262
- return new Promise((resolve2) => setTimeout(resolve2, ms));
262
+ return new Promise((resolve3) => setTimeout(resolve3, ms));
263
263
  }
264
264
  /**
265
265
  * Group results by specified criteria
@@ -1448,7 +1448,7 @@ $ ${cliCommand}
1448
1448
  * Generate mock response for testing
1449
1449
  */
1450
1450
  async generateMockResponse(_prompt) {
1451
- await new Promise((resolve2) => setTimeout(resolve2, 500));
1451
+ await new Promise((resolve3) => setTimeout(resolve3, 500));
1452
1452
  const mockResponse = {
1453
1453
  content: JSON.stringify({
1454
1454
  issues: [
@@ -6049,7 +6049,7 @@ var init_check_execution_engine = __esm({
6049
6049
  }
6050
6050
  }
6051
6051
  async sleep(ms) {
6052
- return new Promise((resolve2) => setTimeout(resolve2, ms));
6052
+ return new Promise((resolve3) => setTimeout(resolve3, ms));
6053
6053
  }
6054
6054
  deterministicJitter(baseMs, seedStr) {
6055
6055
  let h = 2166136261;
@@ -7252,6 +7252,27 @@ ${expr}
7252
7252
  dependencyResults.set(depId, depResult);
7253
7253
  }
7254
7254
  }
7255
+ const directDeps = checkConfig.depends_on || [];
7256
+ const failedDeps = [];
7257
+ for (const depId of directDeps) {
7258
+ const depRes = results.get(depId);
7259
+ if (!depRes) continue;
7260
+ const hasFatalCommandFailure = (depRes.issues || []).some((issue) => {
7261
+ const id = issue.ruleId || "";
7262
+ return id.endsWith("/command/execution_error") || id.endsWith("/command/transform_js_error") || id.endsWith("/command/transform_error");
7263
+ });
7264
+ if (hasFatalCommandFailure) failedDeps.push(depId);
7265
+ }
7266
+ if (failedDeps.length > 0) {
7267
+ this.recordSkip(checkName, "dependency_failed");
7268
+ logger.info(`\u23ED Skipped (dependency failed: ${failedDeps.join(", ")})`);
7269
+ return {
7270
+ checkName,
7271
+ error: null,
7272
+ result: { issues: [] },
7273
+ skipped: true
7274
+ };
7275
+ }
7255
7276
  for (const depId of checkConfig.depends_on || []) {
7256
7277
  if (results.has(depId)) {
7257
7278
  const depResult = results.get(depId);
@@ -9085,6 +9106,994 @@ var init_config_merger = __esm({
9085
9106
  }
9086
9107
  });
9087
9108
 
9109
+ // src/generated/config-schema.ts
9110
+ var config_schema_exports = {};
9111
+ __export(config_schema_exports, {
9112
+ configSchema: () => configSchema,
9113
+ default: () => config_schema_default
9114
+ });
9115
+ var configSchema, config_schema_default;
9116
+ var init_config_schema = __esm({
9117
+ "src/generated/config-schema.ts"() {
9118
+ "use strict";
9119
+ configSchema = {
9120
+ "$schema": "http://json-schema.org/draft-07/schema#",
9121
+ "$ref": "#/definitions/VisorConfig",
9122
+ "definitions": {
9123
+ "VisorConfig": {
9124
+ "type": "object",
9125
+ "properties": {
9126
+ "version": {
9127
+ "type": "string",
9128
+ "description": "Configuration version"
9129
+ },
9130
+ "extends": {
9131
+ "anyOf": [
9132
+ {
9133
+ "type": "string"
9134
+ },
9135
+ {
9136
+ "type": "array",
9137
+ "items": {
9138
+ "type": "string"
9139
+ }
9140
+ }
9141
+ ],
9142
+ "description": 'Extends from other configurations - can be file path, HTTP(S) URL, or "default"'
9143
+ },
9144
+ "checks": {
9145
+ "$ref": "#/definitions/Record%3Cstring%2CCheckConfig%3E",
9146
+ "description": "Check configurations"
9147
+ },
9148
+ "output": {
9149
+ "$ref": "#/definitions/OutputConfig",
9150
+ "description": "Output configuration"
9151
+ },
9152
+ "http_server": {
9153
+ "$ref": "#/definitions/HttpServerConfig",
9154
+ "description": "HTTP server configuration for receiving webhooks"
9155
+ },
9156
+ "env": {
9157
+ "$ref": "#/definitions/EnvConfig",
9158
+ "description": "Global environment variables"
9159
+ },
9160
+ "ai_model": {
9161
+ "type": "string",
9162
+ "description": "Global AI model setting"
9163
+ },
9164
+ "ai_provider": {
9165
+ "type": "string",
9166
+ "description": "Global AI provider setting"
9167
+ },
9168
+ "ai_mcp_servers": {
9169
+ "$ref": "#/definitions/Record%3Cstring%2CMcpServerConfig%3E",
9170
+ "description": "Global MCP servers configuration for AI checks"
9171
+ },
9172
+ "max_parallelism": {
9173
+ "type": "number",
9174
+ "description": "Maximum number of checks to run in parallel (default: 3)"
9175
+ },
9176
+ "fail_fast": {
9177
+ "type": "boolean",
9178
+ "description": "Stop execution when any check fails (default: false)"
9179
+ },
9180
+ "fail_if": {
9181
+ "type": "string",
9182
+ "description": "Simple global fail condition - fails if expression evaluates to true"
9183
+ },
9184
+ "failure_conditions": {
9185
+ "$ref": "#/definitions/FailureConditions",
9186
+ "description": "Global failure conditions - optional (deprecated, use fail_if)"
9187
+ },
9188
+ "tag_filter": {
9189
+ "$ref": "#/definitions/TagFilter",
9190
+ "description": "Tag filter for selective check execution"
9191
+ },
9192
+ "routing": {
9193
+ "$ref": "#/definitions/RoutingDefaults",
9194
+ "description": "Optional routing defaults for retry/goto/run policies"
9195
+ }
9196
+ },
9197
+ "required": [
9198
+ "version",
9199
+ "checks",
9200
+ "output"
9201
+ ],
9202
+ "additionalProperties": false,
9203
+ "description": "Main Visor configuration",
9204
+ "patternProperties": {
9205
+ "^x-": {}
9206
+ }
9207
+ },
9208
+ "Record<string,CheckConfig>": {
9209
+ "type": "object",
9210
+ "additionalProperties": {
9211
+ "$ref": "#/definitions/CheckConfig"
9212
+ }
9213
+ },
9214
+ "CheckConfig": {
9215
+ "type": "object",
9216
+ "properties": {
9217
+ "type": {
9218
+ "$ref": "#/definitions/ConfigCheckType",
9219
+ "description": "Type of check to perform (defaults to 'ai' if not specified)"
9220
+ },
9221
+ "prompt": {
9222
+ "type": "string",
9223
+ "description": "AI prompt for the check - can be inline string or file path (auto-detected) - required for AI checks"
9224
+ },
9225
+ "appendPrompt": {
9226
+ "type": "string",
9227
+ "description": "Additional prompt to append when extending configurations - merged with parent prompt"
9228
+ },
9229
+ "exec": {
9230
+ "type": "string",
9231
+ "description": "Command execution with Liquid template support - required for command checks"
9232
+ },
9233
+ "stdin": {
9234
+ "type": "string",
9235
+ "description": "Stdin input for tools with Liquid template support - optional for tool checks"
9236
+ },
9237
+ "url": {
9238
+ "type": "string",
9239
+ "description": "HTTP URL - required for http output checks"
9240
+ },
9241
+ "body": {
9242
+ "type": "string",
9243
+ "description": "HTTP body template (Liquid) - required for http output checks"
9244
+ },
9245
+ "method": {
9246
+ "type": "string",
9247
+ "description": "HTTP method (defaults to POST)"
9248
+ },
9249
+ "headers": {
9250
+ "$ref": "#/definitions/Record%3Cstring%2Cstring%3E",
9251
+ "description": "HTTP headers"
9252
+ },
9253
+ "endpoint": {
9254
+ "type": "string",
9255
+ "description": "HTTP endpoint path - required for http_input checks"
9256
+ },
9257
+ "transform": {
9258
+ "type": "string",
9259
+ "description": "Transform template for http_input data (Liquid) - optional"
9260
+ },
9261
+ "transform_js": {
9262
+ "type": "string",
9263
+ "description": "Transform using JavaScript expressions (evaluated in secure sandbox) - optional"
9264
+ },
9265
+ "schedule": {
9266
+ "type": "string",
9267
+ "description": 'Cron schedule expression (e.g., "0 2 * * *") - optional for any check type'
9268
+ },
9269
+ "focus": {
9270
+ "type": "string",
9271
+ "description": "Focus area for the check (security/performance/style/architecture/all) - optional"
9272
+ },
9273
+ "command": {
9274
+ "type": "string",
9275
+ "description": 'Command that triggers this check (e.g., "review", "security-scan") - optional'
9276
+ },
9277
+ "on": {
9278
+ "type": "array",
9279
+ "items": {
9280
+ "$ref": "#/definitions/EventTrigger"
9281
+ },
9282
+ "description": "Events that trigger this check (defaults to ['manual'] if not specified)"
9283
+ },
9284
+ "triggers": {
9285
+ "type": "array",
9286
+ "items": {
9287
+ "type": "string"
9288
+ },
9289
+ "description": "File patterns that trigger this check (optional)"
9290
+ },
9291
+ "ai": {
9292
+ "$ref": "#/definitions/AIProviderConfig",
9293
+ "description": "AI provider configuration (optional)"
9294
+ },
9295
+ "ai_model": {
9296
+ "type": "string",
9297
+ "description": "AI model to use for this check - overrides global setting"
9298
+ },
9299
+ "ai_provider": {
9300
+ "type": "string",
9301
+ "description": "AI provider to use for this check - overrides global setting"
9302
+ },
9303
+ "ai_mcp_servers": {
9304
+ "$ref": "#/definitions/Record%3Cstring%2CMcpServerConfig%3E",
9305
+ "description": "MCP servers for this AI check - overrides global setting"
9306
+ },
9307
+ "claude_code": {
9308
+ "$ref": "#/definitions/ClaudeCodeConfig",
9309
+ "description": "Claude Code configuration (for claude-code type checks)"
9310
+ },
9311
+ "env": {
9312
+ "$ref": "#/definitions/EnvConfig",
9313
+ "description": "Environment variables for this check"
9314
+ },
9315
+ "depends_on": {
9316
+ "type": "array",
9317
+ "items": {
9318
+ "type": "string"
9319
+ },
9320
+ "description": "Check IDs that this check depends on (optional)"
9321
+ },
9322
+ "group": {
9323
+ "type": "string",
9324
+ "description": 'Group name for comment separation (e.g., "code-review", "pr-overview") - optional'
9325
+ },
9326
+ "schema": {
9327
+ "anyOf": [
9328
+ {
9329
+ "type": "string"
9330
+ },
9331
+ {
9332
+ "$ref": "#/definitions/Record%3Cstring%2Cunknown%3E"
9333
+ }
9334
+ ],
9335
+ "description": 'Schema type for template rendering (e.g., "code-review", "markdown") or inline JSON schema object - optional'
9336
+ },
9337
+ "template": {
9338
+ "$ref": "#/definitions/CustomTemplateConfig",
9339
+ "description": "Custom template configuration - optional"
9340
+ },
9341
+ "if": {
9342
+ "type": "string",
9343
+ "description": "Condition to determine if check should run - runs if expression evaluates to true"
9344
+ },
9345
+ "reuse_ai_session": {
9346
+ "type": "boolean",
9347
+ "description": "Whether to reuse AI session from dependency checks (only works with depends_on)"
9348
+ },
9349
+ "fail_if": {
9350
+ "type": "string",
9351
+ "description": "Simple fail condition - fails check if expression evaluates to true"
9352
+ },
9353
+ "failure_conditions": {
9354
+ "$ref": "#/definitions/FailureConditions",
9355
+ "description": "Check-specific failure conditions - optional (deprecated, use fail_if)"
9356
+ },
9357
+ "tags": {
9358
+ "type": "array",
9359
+ "items": {
9360
+ "type": "string"
9361
+ },
9362
+ "description": 'Tags for categorizing and filtering checks (e.g., ["local", "fast", "security"])'
9363
+ },
9364
+ "forEach": {
9365
+ "type": "boolean",
9366
+ "description": "Process output as array and run dependent checks for each item"
9367
+ },
9368
+ "on_fail": {
9369
+ "$ref": "#/definitions/OnFailConfig",
9370
+ "description": "Failure routing configuration for this check (retry/goto/run)"
9371
+ },
9372
+ "on_success": {
9373
+ "$ref": "#/definitions/OnSuccessConfig",
9374
+ "description": "Success routing configuration for this check (post-actions and optional goto)"
9375
+ }
9376
+ },
9377
+ "additionalProperties": false,
9378
+ "description": "Configuration for a single check",
9379
+ "patternProperties": {
9380
+ "^x-": {}
9381
+ }
9382
+ },
9383
+ "ConfigCheckType": {
9384
+ "type": "string",
9385
+ "enum": [
9386
+ "ai",
9387
+ "command",
9388
+ "http",
9389
+ "http_input",
9390
+ "http_client",
9391
+ "noop",
9392
+ "log",
9393
+ "claude-code"
9394
+ ],
9395
+ "description": "Valid check types in configuration"
9396
+ },
9397
+ "Record<string,string>": {
9398
+ "type": "object",
9399
+ "additionalProperties": {
9400
+ "type": "string"
9401
+ }
9402
+ },
9403
+ "EventTrigger": {
9404
+ "type": "string",
9405
+ "enum": [
9406
+ "pr_opened",
9407
+ "pr_updated",
9408
+ "pr_closed",
9409
+ "issue_opened",
9410
+ "issue_comment",
9411
+ "manual",
9412
+ "schedule",
9413
+ "webhook_received"
9414
+ ],
9415
+ "description": "Valid event triggers for checks"
9416
+ },
9417
+ "AIProviderConfig": {
9418
+ "type": "object",
9419
+ "properties": {
9420
+ "provider": {
9421
+ "type": "string",
9422
+ "enum": [
9423
+ "google",
9424
+ "anthropic",
9425
+ "openai",
9426
+ "bedrock",
9427
+ "mock"
9428
+ ],
9429
+ "description": "AI provider to use"
9430
+ },
9431
+ "model": {
9432
+ "type": "string",
9433
+ "description": "Model name to use"
9434
+ },
9435
+ "apiKey": {
9436
+ "type": "string",
9437
+ "description": "API key (usually from environment variables)"
9438
+ },
9439
+ "timeout": {
9440
+ "type": "number",
9441
+ "description": "Request timeout in milliseconds"
9442
+ },
9443
+ "debug": {
9444
+ "type": "boolean",
9445
+ "description": "Enable debug mode"
9446
+ },
9447
+ "mcpServers": {
9448
+ "$ref": "#/definitions/Record%3Cstring%2CMcpServerConfig%3E",
9449
+ "description": "MCP servers configuration"
9450
+ }
9451
+ },
9452
+ "additionalProperties": false,
9453
+ "description": "AI provider configuration",
9454
+ "patternProperties": {
9455
+ "^x-": {}
9456
+ }
9457
+ },
9458
+ "Record<string,McpServerConfig>": {
9459
+ "type": "object",
9460
+ "additionalProperties": {
9461
+ "$ref": "#/definitions/McpServerConfig"
9462
+ }
9463
+ },
9464
+ "McpServerConfig": {
9465
+ "type": "object",
9466
+ "properties": {
9467
+ "command": {
9468
+ "type": "string",
9469
+ "description": "Command to execute for the MCP server"
9470
+ },
9471
+ "args": {
9472
+ "type": "array",
9473
+ "items": {
9474
+ "type": "string"
9475
+ },
9476
+ "description": "Arguments to pass to the command"
9477
+ },
9478
+ "env": {
9479
+ "$ref": "#/definitions/Record%3Cstring%2Cstring%3E",
9480
+ "description": "Environment variables for the MCP server"
9481
+ }
9482
+ },
9483
+ "required": [
9484
+ "command"
9485
+ ],
9486
+ "additionalProperties": false,
9487
+ "description": "MCP Server configuration",
9488
+ "patternProperties": {
9489
+ "^x-": {}
9490
+ }
9491
+ },
9492
+ "ClaudeCodeConfig": {
9493
+ "type": "object",
9494
+ "properties": {
9495
+ "allowedTools": {
9496
+ "type": "array",
9497
+ "items": {
9498
+ "type": "string"
9499
+ },
9500
+ "description": "List of allowed tools for Claude Code to use"
9501
+ },
9502
+ "maxTurns": {
9503
+ "type": "number",
9504
+ "description": "Maximum number of turns in conversation"
9505
+ },
9506
+ "systemPrompt": {
9507
+ "type": "string",
9508
+ "description": "System prompt for Claude Code"
9509
+ },
9510
+ "mcpServers": {
9511
+ "$ref": "#/definitions/Record%3Cstring%2CMcpServerConfig%3E",
9512
+ "description": "MCP servers configuration"
9513
+ },
9514
+ "subagent": {
9515
+ "type": "string",
9516
+ "description": "Path to subagent script"
9517
+ },
9518
+ "hooks": {
9519
+ "type": "object",
9520
+ "properties": {
9521
+ "onStart": {
9522
+ "type": "string",
9523
+ "description": "Called when check starts"
9524
+ },
9525
+ "onEnd": {
9526
+ "type": "string",
9527
+ "description": "Called when check ends"
9528
+ },
9529
+ "onError": {
9530
+ "type": "string",
9531
+ "description": "Called when check encounters an error"
9532
+ }
9533
+ },
9534
+ "additionalProperties": false,
9535
+ "description": "Event hooks for lifecycle management",
9536
+ "patternProperties": {
9537
+ "^x-": {}
9538
+ }
9539
+ }
9540
+ },
9541
+ "additionalProperties": false,
9542
+ "description": "Claude Code configuration",
9543
+ "patternProperties": {
9544
+ "^x-": {}
9545
+ }
9546
+ },
9547
+ "EnvConfig": {
9548
+ "type": "object",
9549
+ "additionalProperties": {
9550
+ "type": [
9551
+ "string",
9552
+ "number",
9553
+ "boolean"
9554
+ ]
9555
+ },
9556
+ "description": "Environment variable reference configuration"
9557
+ },
9558
+ "Record<string,unknown>": {
9559
+ "type": "object",
9560
+ "additionalProperties": {}
9561
+ },
9562
+ "CustomTemplateConfig": {
9563
+ "type": "object",
9564
+ "properties": {
9565
+ "file": {
9566
+ "type": "string",
9567
+ "description": "Path to custom template file (relative to config file or absolute)"
9568
+ },
9569
+ "content": {
9570
+ "type": "string",
9571
+ "description": "Raw template content as string"
9572
+ }
9573
+ },
9574
+ "additionalProperties": false,
9575
+ "description": "Custom template configuration",
9576
+ "patternProperties": {
9577
+ "^x-": {}
9578
+ }
9579
+ },
9580
+ "FailureConditions": {
9581
+ "type": "object",
9582
+ "additionalProperties": {
9583
+ "$ref": "#/definitions/FailureCondition"
9584
+ },
9585
+ "description": "Collection of failure conditions"
9586
+ },
9587
+ "FailureCondition": {
9588
+ "anyOf": [
9589
+ {
9590
+ "$ref": "#/definitions/SimpleFailureCondition"
9591
+ },
9592
+ {
9593
+ "$ref": "#/definitions/ComplexFailureCondition"
9594
+ }
9595
+ ],
9596
+ "description": "Failure condition - can be a simple expression string or complex object"
9597
+ },
9598
+ "SimpleFailureCondition": {
9599
+ "type": "string",
9600
+ "description": "Simple failure condition - just an expression string"
9601
+ },
9602
+ "ComplexFailureCondition": {
9603
+ "type": "object",
9604
+ "properties": {
9605
+ "condition": {
9606
+ "type": "string",
9607
+ "description": "Expression to evaluate using Function Constructor"
9608
+ },
9609
+ "message": {
9610
+ "type": "string",
9611
+ "description": "Human-readable message when condition is met"
9612
+ },
9613
+ "severity": {
9614
+ "$ref": "#/definitions/FailureConditionSeverity",
9615
+ "description": "Severity level of the failure"
9616
+ },
9617
+ "halt_execution": {
9618
+ "type": "boolean",
9619
+ "description": "Whether this condition should halt execution"
9620
+ }
9621
+ },
9622
+ "required": [
9623
+ "condition"
9624
+ ],
9625
+ "additionalProperties": false,
9626
+ "description": "Complex failure condition with additional metadata",
9627
+ "patternProperties": {
9628
+ "^x-": {}
9629
+ }
9630
+ },
9631
+ "FailureConditionSeverity": {
9632
+ "type": "string",
9633
+ "enum": [
9634
+ "error",
9635
+ "warning",
9636
+ "info"
9637
+ ],
9638
+ "description": "Failure condition severity levels"
9639
+ },
9640
+ "OnFailConfig": {
9641
+ "type": "object",
9642
+ "properties": {
9643
+ "retry": {
9644
+ "$ref": "#/definitions/RetryPolicy",
9645
+ "description": "Retry policy"
9646
+ },
9647
+ "run": {
9648
+ "type": "array",
9649
+ "items": {
9650
+ "type": "string"
9651
+ },
9652
+ "description": "Remediation steps to run before reattempt"
9653
+ },
9654
+ "goto": {
9655
+ "type": "string",
9656
+ "description": "Jump back to an ancestor step (by id)"
9657
+ },
9658
+ "goto_js": {
9659
+ "type": "string",
9660
+ "description": "Dynamic goto: JS expression returning step id or null"
9661
+ },
9662
+ "run_js": {
9663
+ "type": "string",
9664
+ "description": "Dynamic remediation list: JS expression returning string[]"
9665
+ }
9666
+ },
9667
+ "additionalProperties": false,
9668
+ "description": "Failure routing configuration per check",
9669
+ "patternProperties": {
9670
+ "^x-": {}
9671
+ }
9672
+ },
9673
+ "RetryPolicy": {
9674
+ "type": "object",
9675
+ "properties": {
9676
+ "max": {
9677
+ "type": "number",
9678
+ "description": "Maximum retry attempts (excluding the first attempt)"
9679
+ },
9680
+ "backoff": {
9681
+ "$ref": "#/definitions/BackoffPolicy",
9682
+ "description": "Backoff policy"
9683
+ }
9684
+ },
9685
+ "additionalProperties": false,
9686
+ "description": "Retry policy for a step",
9687
+ "patternProperties": {
9688
+ "^x-": {}
9689
+ }
9690
+ },
9691
+ "BackoffPolicy": {
9692
+ "type": "object",
9693
+ "properties": {
9694
+ "mode": {
9695
+ "type": "string",
9696
+ "enum": [
9697
+ "fixed",
9698
+ "exponential"
9699
+ ],
9700
+ "description": "Backoff mode"
9701
+ },
9702
+ "delay_ms": {
9703
+ "type": "number",
9704
+ "description": "Initial delay in milliseconds"
9705
+ }
9706
+ },
9707
+ "additionalProperties": false,
9708
+ "description": "Backoff policy for retries",
9709
+ "patternProperties": {
9710
+ "^x-": {}
9711
+ }
9712
+ },
9713
+ "OnSuccessConfig": {
9714
+ "type": "object",
9715
+ "properties": {
9716
+ "run": {
9717
+ "type": "array",
9718
+ "items": {
9719
+ "type": "string"
9720
+ },
9721
+ "description": "Post-success steps to run"
9722
+ },
9723
+ "goto": {
9724
+ "type": "string",
9725
+ "description": "Optional jump back to ancestor step (by id)"
9726
+ },
9727
+ "goto_js": {
9728
+ "type": "string",
9729
+ "description": "Dynamic goto: JS expression returning step id or null"
9730
+ },
9731
+ "run_js": {
9732
+ "type": "string",
9733
+ "description": "Dynamic post-success steps: JS expression returning string[]"
9734
+ }
9735
+ },
9736
+ "additionalProperties": false,
9737
+ "description": "Success routing configuration per check",
9738
+ "patternProperties": {
9739
+ "^x-": {}
9740
+ }
9741
+ },
9742
+ "OutputConfig": {
9743
+ "type": "object",
9744
+ "properties": {
9745
+ "pr_comment": {
9746
+ "$ref": "#/definitions/PrCommentOutput",
9747
+ "description": "PR comment configuration"
9748
+ },
9749
+ "file_comment": {
9750
+ "$ref": "#/definitions/FileCommentOutput",
9751
+ "description": "File comment configuration (optional)"
9752
+ },
9753
+ "github_checks": {
9754
+ "$ref": "#/definitions/GitHubCheckOutput",
9755
+ "description": "GitHub check runs configuration (optional)"
9756
+ },
9757
+ "suppressionEnabled": {
9758
+ "type": "boolean",
9759
+ "description": "Whether to enable issue suppression via visor-disable comments (default: true)"
9760
+ }
9761
+ },
9762
+ "required": [
9763
+ "pr_comment"
9764
+ ],
9765
+ "additionalProperties": false,
9766
+ "description": "Output configuration",
9767
+ "patternProperties": {
9768
+ "^x-": {}
9769
+ }
9770
+ },
9771
+ "PrCommentOutput": {
9772
+ "type": "object",
9773
+ "properties": {
9774
+ "format": {
9775
+ "$ref": "#/definitions/ConfigOutputFormat",
9776
+ "description": "Format of the output"
9777
+ },
9778
+ "group_by": {
9779
+ "$ref": "#/definitions/GroupByOption",
9780
+ "description": "How to group the results"
9781
+ },
9782
+ "collapse": {
9783
+ "type": "boolean",
9784
+ "description": "Whether to collapse sections by default"
9785
+ },
9786
+ "debug": {
9787
+ "$ref": "#/definitions/DebugConfig",
9788
+ "description": "Debug mode configuration (optional)"
9789
+ }
9790
+ },
9791
+ "required": [
9792
+ "format",
9793
+ "group_by",
9794
+ "collapse"
9795
+ ],
9796
+ "additionalProperties": false,
9797
+ "description": "PR comment output configuration",
9798
+ "patternProperties": {
9799
+ "^x-": {}
9800
+ }
9801
+ },
9802
+ "ConfigOutputFormat": {
9803
+ "type": "string",
9804
+ "enum": [
9805
+ "table",
9806
+ "json",
9807
+ "markdown",
9808
+ "sarif"
9809
+ ],
9810
+ "description": "Valid output formats"
9811
+ },
9812
+ "GroupByOption": {
9813
+ "type": "string",
9814
+ "enum": [
9815
+ "check",
9816
+ "file",
9817
+ "severity"
9818
+ ],
9819
+ "description": "Valid grouping options"
9820
+ },
9821
+ "DebugConfig": {
9822
+ "type": "object",
9823
+ "properties": {
9824
+ "enabled": {
9825
+ "type": "boolean",
9826
+ "description": "Enable debug mode"
9827
+ },
9828
+ "includePrompts": {
9829
+ "type": "boolean",
9830
+ "description": "Include AI prompts in debug output"
9831
+ },
9832
+ "includeRawResponses": {
9833
+ "type": "boolean",
9834
+ "description": "Include raw AI responses in debug output"
9835
+ },
9836
+ "includeTiming": {
9837
+ "type": "boolean",
9838
+ "description": "Include timing information"
9839
+ },
9840
+ "includeProviderInfo": {
9841
+ "type": "boolean",
9842
+ "description": "Include provider information"
9843
+ }
9844
+ },
9845
+ "required": [
9846
+ "enabled",
9847
+ "includePrompts",
9848
+ "includeRawResponses",
9849
+ "includeTiming",
9850
+ "includeProviderInfo"
9851
+ ],
9852
+ "additionalProperties": false,
9853
+ "description": "Debug mode configuration",
9854
+ "patternProperties": {
9855
+ "^x-": {}
9856
+ }
9857
+ },
9858
+ "FileCommentOutput": {
9859
+ "type": "object",
9860
+ "properties": {
9861
+ "enabled": {
9862
+ "type": "boolean",
9863
+ "description": "Whether file comments are enabled"
9864
+ },
9865
+ "inline": {
9866
+ "type": "boolean",
9867
+ "description": "Whether to show inline comments"
9868
+ }
9869
+ },
9870
+ "required": [
9871
+ "enabled",
9872
+ "inline"
9873
+ ],
9874
+ "additionalProperties": false,
9875
+ "description": "File comment output configuration",
9876
+ "patternProperties": {
9877
+ "^x-": {}
9878
+ }
9879
+ },
9880
+ "GitHubCheckOutput": {
9881
+ "type": "object",
9882
+ "properties": {
9883
+ "enabled": {
9884
+ "type": "boolean",
9885
+ "description": "Whether GitHub check runs are enabled"
9886
+ },
9887
+ "per_check": {
9888
+ "type": "boolean",
9889
+ "description": "Whether to create individual check runs per configured check"
9890
+ },
9891
+ "name_prefix": {
9892
+ "type": "string",
9893
+ "description": "Custom name prefix for check runs"
9894
+ }
9895
+ },
9896
+ "required": [
9897
+ "enabled",
9898
+ "per_check"
9899
+ ],
9900
+ "additionalProperties": false,
9901
+ "description": "GitHub Check Runs output configuration",
9902
+ "patternProperties": {
9903
+ "^x-": {}
9904
+ }
9905
+ },
9906
+ "HttpServerConfig": {
9907
+ "type": "object",
9908
+ "properties": {
9909
+ "enabled": {
9910
+ "type": "boolean",
9911
+ "description": "Whether HTTP server is enabled"
9912
+ },
9913
+ "port": {
9914
+ "type": "number",
9915
+ "description": "Port to listen on"
9916
+ },
9917
+ "host": {
9918
+ "type": "string",
9919
+ "description": "Host/IP to bind to (defaults to 0.0.0.0)"
9920
+ },
9921
+ "tls": {
9922
+ "$ref": "#/definitions/TlsConfig",
9923
+ "description": "TLS/SSL configuration for HTTPS"
9924
+ },
9925
+ "auth": {
9926
+ "$ref": "#/definitions/HttpAuthConfig",
9927
+ "description": "Authentication configuration"
9928
+ },
9929
+ "endpoints": {
9930
+ "type": "array",
9931
+ "items": {
9932
+ "$ref": "#/definitions/HttpEndpointConfig"
9933
+ },
9934
+ "description": "HTTP endpoints configuration"
9935
+ }
9936
+ },
9937
+ "required": [
9938
+ "enabled",
9939
+ "port"
9940
+ ],
9941
+ "additionalProperties": false,
9942
+ "description": "HTTP server configuration for receiving webhooks",
9943
+ "patternProperties": {
9944
+ "^x-": {}
9945
+ }
9946
+ },
9947
+ "TlsConfig": {
9948
+ "type": "object",
9949
+ "properties": {
9950
+ "enabled": {
9951
+ "type": "boolean",
9952
+ "description": "Enable TLS/HTTPS"
9953
+ },
9954
+ "cert": {
9955
+ "type": "string",
9956
+ "description": "Path to TLS certificate file or certificate content"
9957
+ },
9958
+ "key": {
9959
+ "type": "string",
9960
+ "description": "Path to TLS key file or key content"
9961
+ },
9962
+ "ca": {
9963
+ "type": "string",
9964
+ "description": "Path to CA certificate file or CA content (optional)"
9965
+ },
9966
+ "rejectUnauthorized": {
9967
+ "type": "boolean",
9968
+ "description": "Reject unauthorized connections (default: true)"
9969
+ }
9970
+ },
9971
+ "required": [
9972
+ "enabled"
9973
+ ],
9974
+ "additionalProperties": false,
9975
+ "description": "TLS/SSL configuration for HTTPS server",
9976
+ "patternProperties": {
9977
+ "^x-": {}
9978
+ }
9979
+ },
9980
+ "HttpAuthConfig": {
9981
+ "type": "object",
9982
+ "properties": {
9983
+ "type": {
9984
+ "type": "string",
9985
+ "enum": [
9986
+ "bearer_token",
9987
+ "hmac",
9988
+ "basic",
9989
+ "none"
9990
+ ],
9991
+ "description": "Authentication type"
9992
+ },
9993
+ "secret": {
9994
+ "type": "string",
9995
+ "description": "Secret or token for authentication"
9996
+ },
9997
+ "username": {
9998
+ "type": "string",
9999
+ "description": "Username for basic auth"
10000
+ },
10001
+ "password": {
10002
+ "type": "string",
10003
+ "description": "Password for basic auth"
10004
+ }
10005
+ },
10006
+ "required": [
10007
+ "type"
10008
+ ],
10009
+ "additionalProperties": false,
10010
+ "description": "HTTP server authentication configuration",
10011
+ "patternProperties": {
10012
+ "^x-": {}
10013
+ }
10014
+ },
10015
+ "HttpEndpointConfig": {
10016
+ "type": "object",
10017
+ "properties": {
10018
+ "path": {
10019
+ "type": "string",
10020
+ "description": "Path for the webhook endpoint"
10021
+ },
10022
+ "transform": {
10023
+ "type": "string",
10024
+ "description": "Optional transform template (Liquid) for the received data"
10025
+ },
10026
+ "name": {
10027
+ "type": "string",
10028
+ "description": "Optional name/ID for this endpoint"
10029
+ }
10030
+ },
10031
+ "required": [
10032
+ "path"
10033
+ ],
10034
+ "additionalProperties": false,
10035
+ "description": "HTTP server endpoint configuration",
10036
+ "patternProperties": {
10037
+ "^x-": {}
10038
+ }
10039
+ },
10040
+ "TagFilter": {
10041
+ "type": "object",
10042
+ "properties": {
10043
+ "include": {
10044
+ "type": "array",
10045
+ "items": {
10046
+ "type": "string"
10047
+ },
10048
+ "description": "Tags that checks must have to be included (ANY match)"
10049
+ },
10050
+ "exclude": {
10051
+ "type": "array",
10052
+ "items": {
10053
+ "type": "string"
10054
+ },
10055
+ "description": "Tags that will exclude checks if present (ANY match)"
10056
+ }
10057
+ },
10058
+ "additionalProperties": false,
10059
+ "description": "Tag filter configuration for selective check execution",
10060
+ "patternProperties": {
10061
+ "^x-": {}
10062
+ }
10063
+ },
10064
+ "RoutingDefaults": {
10065
+ "type": "object",
10066
+ "properties": {
10067
+ "max_loops": {
10068
+ "type": "number",
10069
+ "description": "Per-scope cap on routing transitions (success + failure)"
10070
+ },
10071
+ "defaults": {
10072
+ "type": "object",
10073
+ "properties": {
10074
+ "on_fail": {
10075
+ "$ref": "#/definitions/OnFailConfig"
10076
+ }
10077
+ },
10078
+ "additionalProperties": false,
10079
+ "description": "Default policies applied to checks (step-level overrides take precedence)",
10080
+ "patternProperties": {
10081
+ "^x-": {}
10082
+ }
10083
+ }
10084
+ },
10085
+ "additionalProperties": false,
10086
+ "description": "Global routing defaults",
10087
+ "patternProperties": {
10088
+ "^x-": {}
10089
+ }
10090
+ }
10091
+ }
10092
+ };
10093
+ config_schema_default = configSchema;
10094
+ }
10095
+ });
10096
+
9088
10097
  // src/sdk.ts
9089
10098
  var sdk_exports = {};
9090
10099
  __export(sdk_exports, {
@@ -9099,6 +10108,7 @@ init_check_execution_engine();
9099
10108
  var yaml2 = __toESM(require("js-yaml"));
9100
10109
  var fs7 = __toESM(require("fs"));
9101
10110
  var path7 = __toESM(require("path"));
10111
+ init_logger();
9102
10112
  var import_simple_git2 = __toESM(require("simple-git"));
9103
10113
 
9104
10114
  // src/utils/config-loader.ts
@@ -9443,6 +10453,8 @@ var ConfigLoader = class {
9443
10453
 
9444
10454
  // src/config.ts
9445
10455
  init_config_merger();
10456
+ var import_ajv = __toESM(require("ajv"));
10457
+ var import_ajv_formats = __toESM(require("ajv-formats"));
9446
10458
  var ConfigManager = class {
9447
10459
  validCheckTypes = [
9448
10460
  "ai",
@@ -9695,6 +10707,8 @@ var ConfigManager = class {
9695
10707
  */
9696
10708
  validateConfig(config) {
9697
10709
  const errors = [];
10710
+ const warnings = [];
10711
+ this.validateWithAjvSchema(config, errors, warnings);
9698
10712
  if (!config.version) {
9699
10713
  errors.push({
9700
10714
  field: "version",
@@ -9712,8 +10726,38 @@ var ConfigManager = class {
9712
10726
  checkConfig.type = "ai";
9713
10727
  }
9714
10728
  this.validateCheckConfig(checkName, checkConfig, errors);
10729
+ if (checkConfig.ai_mcp_servers) {
10730
+ this.validateMcpServersObject(
10731
+ checkConfig.ai_mcp_servers,
10732
+ `checks.${checkName}.ai_mcp_servers`,
10733
+ errors,
10734
+ warnings
10735
+ );
10736
+ }
10737
+ if (checkConfig.ai?.mcpServers) {
10738
+ this.validateMcpServersObject(
10739
+ checkConfig.ai.mcpServers,
10740
+ `checks.${checkName}.ai.mcpServers`,
10741
+ errors,
10742
+ warnings
10743
+ );
10744
+ }
10745
+ if (checkConfig.ai_mcp_servers && checkConfig.ai?.mcpServers) {
10746
+ const lower = Object.keys(checkConfig.ai_mcp_servers);
10747
+ const higher = Object.keys(checkConfig.ai.mcpServers);
10748
+ const overridden = lower.filter((k) => higher.includes(k));
10749
+ warnings.push({
10750
+ field: `checks.${checkName}.ai.mcpServers`,
10751
+ message: overridden.length > 0 ? `Both ai_mcp_servers and ai.mcpServers are set; ai.mcpServers overrides these servers: ${overridden.join(
10752
+ ", "
10753
+ )}` : "Both ai_mcp_servers and ai.mcpServers are set; ai.mcpServers takes precedence for this check."
10754
+ });
10755
+ }
9715
10756
  }
9716
10757
  }
10758
+ if (config.ai_mcp_servers) {
10759
+ this.validateMcpServersObject(config.ai_mcp_servers, "ai_mcp_servers", errors, warnings);
10760
+ }
9717
10761
  if (config.output) {
9718
10762
  this.validateOutputConfig(config.output, errors);
9719
10763
  }
@@ -9738,6 +10782,11 @@ var ConfigManager = class {
9738
10782
  if (errors.length > 0) {
9739
10783
  throw new Error(errors[0].message);
9740
10784
  }
10785
+ if (warnings.length > 0) {
10786
+ for (const w of warnings) {
10787
+ logger.warn(`\u26A0\uFE0F Config warning [${w.field}]: ${w.message}`);
10788
+ }
10789
+ }
9741
10790
  }
9742
10791
  /**
9743
10792
  * Validate individual check configuration
@@ -9863,6 +10912,122 @@ var ConfigManager = class {
9863
10912
  }
9864
10913
  }
9865
10914
  }
10915
+ /**
10916
+ * Validate MCP servers object shape and values (basic shape only)
10917
+ */
10918
+ validateMcpServersObject(mcpServers, fieldPrefix, errors, _warnings) {
10919
+ if (typeof mcpServers !== "object" || mcpServers === null) {
10920
+ errors.push({
10921
+ field: fieldPrefix,
10922
+ message: `${fieldPrefix} must be an object mapping server names to { command, args?, env? }`,
10923
+ value: mcpServers
10924
+ });
10925
+ return;
10926
+ }
10927
+ for (const [serverName, cfg] of Object.entries(mcpServers)) {
10928
+ const pathStr = `${fieldPrefix}.${serverName}`;
10929
+ if (!cfg || typeof cfg !== "object") {
10930
+ errors.push({ field: pathStr, message: `${pathStr} must be an object`, value: cfg });
10931
+ continue;
10932
+ }
10933
+ const { command, args, env } = cfg;
10934
+ if (typeof command !== "string" || command.trim() === "") {
10935
+ errors.push({
10936
+ field: `${pathStr}.command`,
10937
+ message: `${pathStr}.command must be a non-empty string`,
10938
+ value: command
10939
+ });
10940
+ }
10941
+ if (args !== void 0 && !Array.isArray(args)) {
10942
+ errors.push({
10943
+ field: `${pathStr}.args`,
10944
+ message: `${pathStr}.args must be an array of strings`,
10945
+ value: args
10946
+ });
10947
+ }
10948
+ if (env !== void 0) {
10949
+ if (typeof env !== "object" || env === null) {
10950
+ errors.push({
10951
+ field: `${pathStr}.env`,
10952
+ message: `${pathStr}.env must be an object of string values`,
10953
+ value: env
10954
+ });
10955
+ } else {
10956
+ for (const [k, v] of Object.entries(env)) {
10957
+ if (typeof v !== "string") {
10958
+ errors.push({
10959
+ field: `${pathStr}.env.${k}`,
10960
+ message: `${pathStr}.env.${k} must be a string`,
10961
+ value: v
10962
+ });
10963
+ }
10964
+ }
10965
+ }
10966
+ }
10967
+ }
10968
+ }
10969
+ /**
10970
+ * Validate configuration using generated JSON Schema via Ajv, if available.
10971
+ * Adds to errors/warnings but does not throw directly.
10972
+ */
10973
+ validateWithAjvSchema(config, errors, warnings) {
10974
+ try {
10975
+ if (!__ajvValidate) {
10976
+ try {
10977
+ const jsonPath = path7.resolve(__dirname, "generated", "config-schema.json");
10978
+ const jsonSchema = require(jsonPath);
10979
+ if (jsonSchema) {
10980
+ const ajv = new import_ajv.default({ allErrors: true, allowUnionTypes: true, strict: false });
10981
+ (0, import_ajv_formats.default)(ajv);
10982
+ const validate = ajv.compile(jsonSchema);
10983
+ __ajvValidate = (data) => validate(data);
10984
+ __ajvErrors = () => validate.errors;
10985
+ }
10986
+ } catch {
10987
+ }
10988
+ if (!__ajvValidate) {
10989
+ try {
10990
+ const mod = (init_config_schema(), __toCommonJS(config_schema_exports));
10991
+ const schema = mod?.configSchema || mod?.default || mod;
10992
+ if (schema) {
10993
+ const ajv = new import_ajv.default({ allErrors: true, allowUnionTypes: true, strict: false });
10994
+ (0, import_ajv_formats.default)(ajv);
10995
+ const validate = ajv.compile(schema);
10996
+ __ajvValidate = (data) => validate(data);
10997
+ __ajvErrors = () => validate.errors;
10998
+ } else {
10999
+ return;
11000
+ }
11001
+ } catch {
11002
+ return;
11003
+ }
11004
+ }
11005
+ }
11006
+ const ok = __ajvValidate(config);
11007
+ const errs = __ajvErrors ? __ajvErrors() : null;
11008
+ if (!ok && Array.isArray(errs)) {
11009
+ for (const e of errs) {
11010
+ const pathStr = e.instancePath ? e.instancePath.replace(/^\//, "").replace(/\//g, ".") : "";
11011
+ const msg = e.message || "Invalid configuration";
11012
+ if (e.keyword === "additionalProperties") {
11013
+ const addl = e.params && e.params.additionalProperty || "unknown";
11014
+ const fullField = pathStr ? `${pathStr}.${addl}` : addl;
11015
+ const topLevel = !pathStr;
11016
+ warnings.push({
11017
+ field: fullField || "config",
11018
+ message: topLevel ? `Unknown top-level key '${addl}' will be ignored.` : `Unknown key '${addl}' will be ignored`
11019
+ });
11020
+ } else {
11021
+ logger.debug(`Ajv note [${pathStr || "config"}]: ${msg}`);
11022
+ }
11023
+ }
11024
+ }
11025
+ } catch (err) {
11026
+ logger.debug(`Ajv validation skipped: ${err instanceof Error ? err.message : String(err)}`);
11027
+ }
11028
+ }
11029
+ // Unknown-key warnings are fully handled by Ajv using the generated schema
11030
+ // Unknown-key hints are produced by Ajv (additionalProperties=false)
9866
11031
  /**
9867
11032
  * Validate tag filter configuration
9868
11033
  */
@@ -10039,6 +11204,8 @@ var ConfigManager = class {
10039
11204
  return merged;
10040
11205
  }
10041
11206
  };
11207
+ var __ajvValidate = null;
11208
+ var __ajvErrors = null;
10042
11209
 
10043
11210
  // src/sdk.ts
10044
11211
  async function loadConfig(configPath) {