@probelabs/visor 0.1.71 → 0.1.73

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.
@@ -7,8 +7,10 @@ export interface AnalysisResult {
7
7
  executionTime: number;
8
8
  timestamp: string;
9
9
  checksExecuted: string[];
10
+ executionStatistics?: import('./check-execution-engine').ExecutionStatistics;
10
11
  debug?: DebugInfo;
11
12
  failureConditions?: FailureConditionResult[];
13
+ isCodeReview?: boolean;
12
14
  }
13
15
  export interface DebugInfo {
14
16
  provider?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"","sourceRoot":"","sources":["file:///home/runner/work/visor/visor/src/output-formatters.ts"],"names":[],"mappings":"AACA,OAAO,EACL,aAAa,EAMd,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAExD,MAAM,WAAW,cAAc;IAC7B,cAAc,EAAE,iBAAiB,CAAC;IAClC,aAAa,EAAE,aAAa,CAAC;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,iBAAiB,CAAC,EAAE,sBAAsB,EAAE,CAAC;CAC9C;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,KAAK,CAAC;QACrB,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;QACd,cAAc,EAAE,MAAM,CAAC;QACvB,OAAO,EAAE,OAAO,CAAC;KAClB,CAAC,CAAC;CACJ;AAED,MAAM,WAAW,sBAAsB;IACrC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,qBAAa,gBAAgB;IAC3B;;OAEG;IACH,MAAM,CAAC,aAAa,CAAC,MAAM,EAAE,cAAc,EAAE,OAAO,GAAE,sBAA2B,GAAG,MAAM;IA2K1F;;OAEG;IACH,MAAM,CAAC,YAAY,CAAC,MAAM,EAAE,cAAc,EAAE,OAAO,GAAE,sBAA2B,GAAG,MAAM;IAoCzF;;OAEG;IACH,MAAM,CAAC,aAAa,CAAC,MAAM,EAAE,cAAc,EAAE,QAAQ,GAAE,sBAA2B,GAAG,MAAM;IAmI3F;;OAEG;IACH,MAAM,CAAC,gBAAgB,CAAC,MAAM,EAAE,cAAc,EAAE,OAAO,GAAE,sBAA2B,GAAG,MAAM;IAuN7F,OAAO,CAAC,MAAM,CAAC,uBAAuB;IAqBtC;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,cAAc;IAc7B;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,qBAAqB;IAsBpC,OAAO,CAAC,MAAM,CAAC,cAAc;IAU7B,OAAO,CAAC,MAAM,CAAC,kBAAkB;IAUjC,OAAO,CAAC,MAAM,CAAC,gBAAgB;IAU/B,OAAO,CAAC,MAAM,CAAC,YAAY;IAK3B,OAAO,CAAC,MAAM,CAAC,QAAQ;CAmBxB"}
1
+ {"version":3,"file":"","sourceRoot":"","sources":["file:///home/runner/work/visor/visor/src/output-formatters.ts"],"names":[],"mappings":"AACA,OAAO,EACL,aAAa,EAMd,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAExD,MAAM,WAAW,cAAc;IAC7B,cAAc,EAAE,iBAAiB,CAAC;IAClC,aAAa,EAAE,aAAa,CAAC;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,mBAAmB,CAAC,EAAE,OAAO,0BAA0B,EAAE,mBAAmB,CAAC;IAC7E,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,iBAAiB,CAAC,EAAE,sBAAsB,EAAE,CAAC;IAC7C,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,KAAK,CAAC;QACrB,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;QACd,cAAc,EAAE,MAAM,CAAC;QACvB,OAAO,EAAE,OAAO,CAAC;KAClB,CAAC,CAAC;CACJ;AAED,MAAM,WAAW,sBAAsB;IACrC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,qBAAa,gBAAgB;IAC3B;;OAEG;IACH,MAAM,CAAC,aAAa,CAAC,MAAM,EAAE,cAAc,EAAE,OAAO,GAAE,sBAA2B,GAAG,MAAM;IA8L1F;;OAEG;IACH,MAAM,CAAC,YAAY,CAAC,MAAM,EAAE,cAAc,EAAE,OAAO,GAAE,sBAA2B,GAAG,MAAM;IAoCzF;;OAEG;IACH,MAAM,CAAC,aAAa,CAAC,MAAM,EAAE,cAAc,EAAE,QAAQ,GAAE,sBAA2B,GAAG,MAAM;IAmI3F;;OAEG;IACH,MAAM,CAAC,gBAAgB,CAAC,MAAM,EAAE,cAAc,EAAE,OAAO,GAAE,sBAA2B,GAAG,MAAM;IAuN7F,OAAO,CAAC,MAAM,CAAC,uBAAuB;IAqBtC;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,cAAc;IAc7B;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,qBAAqB;IAsBpC,OAAO,CAAC,MAAM,CAAC,cAAc;IAU7B,OAAO,CAAC,MAAM,CAAC,kBAAkB;IAUjC,OAAO,CAAC,MAAM,CAAC,gBAAgB;IAU/B,OAAO,CAAC,MAAM,CAAC,YAAY;IAK3B,OAAO,CAAC,MAAM,CAAC,QAAQ;CAmBxB"}
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  CheckExecutionEngine
3
- } from "./chunk-745RDQD3.mjs";
3
+ } from "./chunk-NINHE4RF.mjs";
4
4
  import "./chunk-FIL2OGF6.mjs";
5
5
  import "./chunk-WMJKH4XE.mjs";
6
6
  export {
7
7
  CheckExecutionEngine
8
8
  };
9
- //# sourceMappingURL=check-execution-engine-TBF6LPYH.mjs.map
9
+ //# sourceMappingURL=check-execution-engine-75SSXUBP.mjs.map
@@ -1032,6 +1032,10 @@ ${schemaString}`);
1032
1032
  // We don't want the agent to modify files
1033
1033
  debug: this.config.debug || false
1034
1034
  };
1035
+ if (this.config.mcpServers && Object.keys(this.config.mcpServers).length > 0) {
1036
+ options.enableMcp = true;
1037
+ options.mcpConfig = { mcpServers: this.config.mcpServers };
1038
+ }
1035
1039
  if (this.config.provider) {
1036
1040
  const providerOverride = this.config.provider === "claude-code" || this.config.provider === "bedrock" ? "anthropic" : this.config.provider === "anthropic" || this.config.provider === "openai" || this.config.provider === "google" ? this.config.provider : void 0;
1037
1041
  if (providerOverride) {
@@ -1489,9 +1493,9 @@ var PRReviewer = class {
1489
1493
  async reviewPR(owner, repo, prNumber, prInfo, options = {}) {
1490
1494
  const { debug = false, config, checks } = options;
1491
1495
  if (config && checks && checks.length > 0) {
1492
- const { CheckExecutionEngine: CheckExecutionEngine2 } = await import("./check-execution-engine-TBF6LPYH.mjs");
1496
+ const { CheckExecutionEngine: CheckExecutionEngine2 } = await import("./check-execution-engine-75SSXUBP.mjs");
1493
1497
  const engine = new CheckExecutionEngine2();
1494
- const groupedResults = await engine.executeGroupedChecks(
1498
+ const { results } = await engine.executeGroupedChecks(
1495
1499
  prInfo,
1496
1500
  checks,
1497
1501
  void 0,
@@ -1499,7 +1503,7 @@ var PRReviewer = class {
1499
1503
  void 0,
1500
1504
  debug
1501
1505
  );
1502
- return groupedResults;
1506
+ return results;
1503
1507
  }
1504
1508
  throw new Error(
1505
1509
  "No configuration provided. Please create a .visor.yaml file with check definitions. Built-in prompts have been removed - all checks must be explicitly configured."
@@ -2528,15 +2532,13 @@ var AICheckProvider = class extends CheckProvider {
2528
2532
  Object.assign(mcpServers, config.ai.mcpServers);
2529
2533
  }
2530
2534
  if (Object.keys(mcpServers).length > 0) {
2535
+ aiConfig.mcpServers = mcpServers;
2531
2536
  const mcpConfig = { mcpServers };
2532
2537
  const mcpTools = await this.setupMcpTools(mcpConfig);
2533
- if (mcpTools.length > 0) {
2534
- aiConfig.tools = mcpTools;
2535
- if (aiConfig.debug) {
2536
- console.error(
2537
- `\u{1F527} Debug: AI check configured with ${mcpTools.length} MCP tools from ${Object.keys(mcpServers).length} servers`
2538
- );
2539
- }
2538
+ if (aiConfig.debug) {
2539
+ console.error(
2540
+ `\u{1F527} Debug: AI check MCP configured with ${Object.keys(mcpServers).length} servers; discovered ${mcpTools.length} tools`
2541
+ );
2540
2542
  }
2541
2543
  }
2542
2544
  const processedPrompt = await this.processPrompt(
@@ -5744,6 +5746,7 @@ var CheckExecutionEngine = class _CheckExecutionEngine {
5744
5746
  config;
5745
5747
  webhookContext;
5746
5748
  routingSandbox;
5749
+ executionStats = /* @__PURE__ */ new Map();
5747
5750
  constructor(workingDirectory) {
5748
5751
  this.workingDirectory = workingDirectory || process.cwd();
5749
5752
  this.gitAnalyzer = new GitRepositoryAnalyzer(this.workingDirectory);
@@ -6282,12 +6285,14 @@ ${expr}
6282
6285
  apiCallDetails: reviewSummary.debug.apiCallDetails
6283
6286
  };
6284
6287
  }
6288
+ const executionStatistics = this.buildExecutionStatistics();
6285
6289
  return {
6286
6290
  repositoryInfo,
6287
6291
  reviewSummary,
6288
6292
  executionTime,
6289
6293
  timestamp,
6290
6294
  checksExecuted: filteredChecks,
6295
+ executionStatistics,
6291
6296
  debug: debugInfo
6292
6297
  };
6293
6298
  } catch (error) {
@@ -6480,7 +6485,7 @@ ${expr}
6480
6485
  });
6481
6486
  }
6482
6487
  /**
6483
- * Execute review checks and return grouped results for new architecture
6488
+ * Execute review checks and return grouped results with statistics for new architecture
6484
6489
  */
6485
6490
  async executeGroupedChecks(prInfo, checks, timeout, config, outputFormat, debug, maxParallelism, failFast, tagFilter) {
6486
6491
  const logFn = outputFormat === "json" || outputFormat === "sarif" ? debug ? console.error : () => {
@@ -6510,7 +6515,10 @@ ${expr}
6510
6515
  checks = tagFilteredChecks;
6511
6516
  if (checks.length === 0) {
6512
6517
  logger.warn("\u26A0\uFE0F No checks remain after tag filtering");
6513
- return {};
6518
+ return {
6519
+ results: {},
6520
+ statistics: this.buildExecutionStatistics()
6521
+ };
6514
6522
  }
6515
6523
  if (!config?.checks) {
6516
6524
  throw new Error("Config with check definitions required for grouped execution");
@@ -6550,9 +6558,15 @@ ${expr}
6550
6558
  );
6551
6559
  const groupedResults = {};
6552
6560
  groupedResults[checkResult.group] = [checkResult];
6553
- return groupedResults;
6561
+ return {
6562
+ results: groupedResults,
6563
+ statistics: this.buildExecutionStatistics()
6564
+ };
6554
6565
  }
6555
- return {};
6566
+ return {
6567
+ results: {},
6568
+ statistics: this.buildExecutionStatistics()
6569
+ };
6556
6570
  }
6557
6571
  /**
6558
6572
  * Execute single check and return grouped result
@@ -6598,7 +6612,7 @@ ${expr}
6598
6612
  };
6599
6613
  }
6600
6614
  /**
6601
- * Execute multiple checks with dependency awareness - return grouped results
6615
+ * Execute multiple checks with dependency awareness - return grouped results with statistics
6602
6616
  */
6603
6617
  async executeGroupedDependencyAwareChecks(prInfo, checks, timeout, config, logFn, debug, maxParallelism, failFast) {
6604
6618
  const reviewSummary = await this.executeDependencyAwareChecks(
@@ -6611,7 +6625,17 @@ ${expr}
6611
6625
  maxParallelism,
6612
6626
  failFast
6613
6627
  );
6614
- return await this.convertReviewSummaryToGroupedResults(reviewSummary, checks, config, prInfo);
6628
+ const executionStatistics = this.buildExecutionStatistics();
6629
+ const groupedResults = await this.convertReviewSummaryToGroupedResults(
6630
+ reviewSummary,
6631
+ checks,
6632
+ config,
6633
+ prInfo
6634
+ );
6635
+ return {
6636
+ results: groupedResults,
6637
+ statistics: executionStatistics
6638
+ };
6615
6639
  }
6616
6640
  /**
6617
6641
  * Convert ReviewSummary to GroupedCheckResults
@@ -6874,9 +6898,9 @@ ${expr}
6874
6898
  let shouldStopExecution = false;
6875
6899
  let completedChecksCount = 0;
6876
6900
  const totalChecksCount = stats.totalChecks;
6877
- let skippedChecksCount = 0;
6878
- let failedChecksCount = 0;
6879
- const executionStartTime = Date.now();
6901
+ for (const checkName of checks) {
6902
+ this.initializeCheckStats(checkName);
6903
+ }
6880
6904
  for (let levelIndex = 0; levelIndex < dependencyGraph.executionOrder.length && !shouldStopExecution; levelIndex++) {
6881
6905
  const executionGroup = dependencyGraph.executionOrder[levelIndex];
6882
6906
  const checksInLevel = executionGroup.parallel;
@@ -7006,11 +7030,13 @@ ${expr}
7006
7030
  }
7007
7031
  let finalResult;
7008
7032
  if (isForEachDependent && forEachParentName) {
7033
+ this.recordForEachPreview(checkName, forEachItems);
7009
7034
  if (debug) {
7010
7035
  log2(
7011
7036
  `\u{1F504} Debug: Check "${checkName}" depends on forEach check "${forEachParentName}", executing ${forEachItems.length} times`
7012
7037
  );
7013
7038
  }
7039
+ logger.info(` Processing ${forEachItems.length} items...`);
7014
7040
  const allIssues = [];
7015
7041
  const allOutputs = [];
7016
7042
  const aggregatedContents = [];
@@ -7067,6 +7093,7 @@ ${expr}
7067
7093
  `\u{1F504} Debug: Executing check "${checkName}" for item ${itemIndex + 1}/${forEachItems.length}`
7068
7094
  );
7069
7095
  }
7096
+ const iterationStart = this.recordIterationStart(checkName);
7070
7097
  const itemResult = await this.executeWithRouting(
7071
7098
  checkName,
7072
7099
  checkConfig,
@@ -7086,6 +7113,17 @@ ${expr}
7086
7113
  parent: forEachParentName
7087
7114
  }
7088
7115
  );
7116
+ const iterationDuration = (Date.now() - iterationStart) / 1e3;
7117
+ this.recordIterationComplete(
7118
+ checkName,
7119
+ iterationStart,
7120
+ true,
7121
+ itemResult.issues || [],
7122
+ itemResult.output
7123
+ );
7124
+ logger.info(
7125
+ ` \u2714 ${itemIndex + 1}/${forEachItems.length} (${iterationDuration.toFixed(1)}s)`
7126
+ );
7089
7127
  return { index: itemIndex, itemResult };
7090
7128
  });
7091
7129
  const forEachConcurrency = Math.max(
@@ -7147,8 +7185,8 @@ ${expr}
7147
7185
  debug
7148
7186
  );
7149
7187
  if (!shouldRun) {
7150
- skippedChecksCount++;
7151
- logger.info(`\u23ED Skipping check: ${checkName} (if condition evaluated to false)`);
7188
+ this.recordSkip(checkName, "if_condition", checkConfig.if);
7189
+ logger.info(`\u23ED Skipped (if: ${this.truncate(checkConfig.if, 40)})`);
7152
7190
  return {
7153
7191
  checkName,
7154
7192
  error: null,
@@ -7172,6 +7210,13 @@ ${expr}
7172
7210
  debug,
7173
7211
  results
7174
7212
  );
7213
+ this.recordIterationComplete(
7214
+ checkName,
7215
+ checkStartTime,
7216
+ true,
7217
+ finalResult.issues || [],
7218
+ finalResult.output
7219
+ );
7175
7220
  if (checkConfig.forEach) {
7176
7221
  try {
7177
7222
  const finalResultWithOutput = finalResult;
@@ -7201,7 +7246,22 @@ ${expr}
7201
7246
  };
7202
7247
  const checkDuration = ((Date.now() - checkStartTime) / 1e3).toFixed(1);
7203
7248
  const issueCount = enrichedIssues.length;
7204
- if (issueCount > 0) {
7249
+ const checkStats = this.executionStats.get(checkName);
7250
+ if (checkStats && checkStats.totalRuns > 1) {
7251
+ if (issueCount > 0) {
7252
+ logger.success(
7253
+ `Check complete: ${checkName} (${checkDuration}s) - ${checkStats.totalRuns} runs, ${issueCount} issue${issueCount === 1 ? "" : "s"}`
7254
+ );
7255
+ } else {
7256
+ logger.success(
7257
+ `Check complete: ${checkName} (${checkDuration}s) - ${checkStats.totalRuns} runs`
7258
+ );
7259
+ }
7260
+ } else if (checkStats && checkStats.outputsProduced && checkStats.outputsProduced > 0) {
7261
+ logger.success(
7262
+ `Check complete: ${checkName} (${checkDuration}s) - ${checkStats.outputsProduced} items`
7263
+ );
7264
+ } else if (issueCount > 0) {
7205
7265
  logger.success(
7206
7266
  `Check complete: ${checkName} (${checkDuration}s) - ${issueCount} issue${issueCount === 1 ? "" : "s"} found`
7207
7267
  );
@@ -7214,9 +7274,10 @@ ${expr}
7214
7274
  result: enrichedResult
7215
7275
  };
7216
7276
  } catch (error) {
7217
- failedChecksCount++;
7218
7277
  const errorMessage = error instanceof Error ? error.message : String(error);
7219
7278
  const checkDuration = ((Date.now() - checkStartTime) / 1e3).toFixed(1);
7279
+ this.recordError(checkName, error instanceof Error ? error : new Error(String(error)));
7280
+ this.recordIterationComplete(checkName, checkStartTime, false, [], void 0);
7220
7281
  logger.error(`\u2716 Check failed: ${checkName} (${checkDuration}s) - ${errorMessage}`);
7221
7282
  if (debug) {
7222
7283
  log2(`\u{1F527} Debug: Error in check ${checkName}: ${errorMessage}`);
@@ -7324,19 +7385,13 @@ ${expr}
7324
7385
  }
7325
7386
  }
7326
7387
  }
7327
- const executionDuration = ((Date.now() - executionStartTime) / 1e3).toFixed(1);
7328
- const successfulChecks = totalChecksCount - failedChecksCount - skippedChecksCount;
7329
- logger.info("");
7330
- logger.step(`Execution complete (${executionDuration}s)`);
7331
- logger.info(` \u2714 Successful: ${successfulChecks}/${totalChecksCount}`);
7332
- if (skippedChecksCount > 0) {
7333
- logger.info(` \u23ED Skipped: ${skippedChecksCount}`);
7334
- }
7335
- if (failedChecksCount > 0) {
7336
- logger.info(` \u2716 Failed: ${failedChecksCount}`);
7388
+ const executionStatistics = this.buildExecutionStatistics();
7389
+ if (logFn === console.log) {
7390
+ this.logExecutionSummary(executionStatistics);
7337
7391
  }
7338
7392
  if (shouldStopExecution) {
7339
- logger.warn(` \u26A0\uFE0F Execution stopped early due to fail-fast`);
7393
+ logger.info("");
7394
+ logger.warn(`\u26A0\uFE0F Execution stopped early due to fail-fast`);
7340
7395
  }
7341
7396
  if (debug) {
7342
7397
  if (shouldStopExecution) {
@@ -8291,9 +8346,223 @@ ${result.value.result.debug.rawResponse}`;
8291
8346
  }
8292
8347
  return "pr_updated";
8293
8348
  }
8349
+ /**
8350
+ * Initialize execution statistics for a check
8351
+ */
8352
+ initializeCheckStats(checkName) {
8353
+ this.executionStats.set(checkName, {
8354
+ checkName,
8355
+ totalRuns: 0,
8356
+ successfulRuns: 0,
8357
+ failedRuns: 0,
8358
+ skipped: false,
8359
+ totalDuration: 0,
8360
+ issuesFound: 0,
8361
+ issuesBySeverity: {
8362
+ critical: 0,
8363
+ error: 0,
8364
+ warning: 0,
8365
+ info: 0
8366
+ },
8367
+ perIterationDuration: []
8368
+ });
8369
+ }
8370
+ /**
8371
+ * Record the start of a check iteration
8372
+ * Returns the start timestamp for duration tracking
8373
+ */
8374
+ recordIterationStart(_checkName) {
8375
+ return Date.now();
8376
+ }
8377
+ /**
8378
+ * Record completion of a check iteration
8379
+ */
8380
+ recordIterationComplete(checkName, startTime, success, issues, output) {
8381
+ const stats = this.executionStats.get(checkName);
8382
+ if (!stats) return;
8383
+ const duration = Date.now() - startTime;
8384
+ stats.totalRuns++;
8385
+ if (success) {
8386
+ stats.successfulRuns++;
8387
+ } else {
8388
+ stats.failedRuns++;
8389
+ }
8390
+ stats.totalDuration += duration;
8391
+ stats.perIterationDuration.push(duration);
8392
+ for (const issue of issues) {
8393
+ stats.issuesFound++;
8394
+ if (issue.severity === "critical") stats.issuesBySeverity.critical++;
8395
+ else if (issue.severity === "error") stats.issuesBySeverity.error++;
8396
+ else if (issue.severity === "warning") stats.issuesBySeverity.warning++;
8397
+ else if (issue.severity === "info") stats.issuesBySeverity.info++;
8398
+ }
8399
+ if (output !== void 0) {
8400
+ stats.outputsProduced = (stats.outputsProduced || 0) + 1;
8401
+ }
8402
+ }
8403
+ /**
8404
+ * Record that a check was skipped
8405
+ */
8406
+ recordSkip(checkName, reason, condition) {
8407
+ const stats = this.executionStats.get(checkName);
8408
+ if (!stats) return;
8409
+ stats.skipped = true;
8410
+ stats.skipReason = reason;
8411
+ if (condition) {
8412
+ stats.skipCondition = condition;
8413
+ }
8414
+ }
8415
+ /**
8416
+ * Record forEach preview items
8417
+ */
8418
+ recordForEachPreview(checkName, items) {
8419
+ const stats = this.executionStats.get(checkName);
8420
+ if (!stats || !items.length) return;
8421
+ const preview = items.slice(0, 3).map((item) => {
8422
+ const str = typeof item === "string" ? item : JSON.stringify(item);
8423
+ return str.length > 50 ? str.substring(0, 47) + "..." : str;
8424
+ });
8425
+ if (items.length > 3) {
8426
+ preview.push(`...${items.length - 3} more`);
8427
+ }
8428
+ stats.forEachPreview = preview;
8429
+ }
8430
+ /**
8431
+ * Record an error for a check
8432
+ */
8433
+ recordError(checkName, error) {
8434
+ const stats = this.executionStats.get(checkName);
8435
+ if (!stats) return;
8436
+ stats.errorMessage = error instanceof Error ? error.message : String(error);
8437
+ }
8438
+ /**
8439
+ * Build the final execution statistics object
8440
+ */
8441
+ buildExecutionStatistics() {
8442
+ const checks = Array.from(this.executionStats.values());
8443
+ const totalExecutions = checks.reduce((sum, s) => sum + s.totalRuns, 0);
8444
+ const successfulExecutions = checks.reduce((sum, s) => sum + s.successfulRuns, 0);
8445
+ const failedExecutions = checks.reduce((sum, s) => sum + s.failedRuns, 0);
8446
+ const skippedChecks = checks.filter((s) => s.skipped).length;
8447
+ const totalDuration = checks.reduce((sum, s) => sum + s.totalDuration, 0);
8448
+ return {
8449
+ totalChecksConfigured: checks.length,
8450
+ totalExecutions,
8451
+ successfulExecutions,
8452
+ failedExecutions,
8453
+ skippedChecks,
8454
+ totalDuration,
8455
+ checks
8456
+ };
8457
+ }
8458
+ /**
8459
+ * Truncate a string to max length with ellipsis
8460
+ */
8461
+ truncate(str, maxLen) {
8462
+ if (str.length <= maxLen) return str;
8463
+ return str.substring(0, maxLen - 3) + "...";
8464
+ }
8465
+ /**
8466
+ * Format the Status column for execution summary table
8467
+ */
8468
+ formatStatusColumn(stats) {
8469
+ if (stats.skipped) {
8470
+ if (stats.skipReason === "if_condition") return "\u23ED if";
8471
+ if (stats.skipReason === "fail_fast") return "\u23ED ff";
8472
+ if (stats.skipReason === "dependency_failed") return "\u23ED dep";
8473
+ return "\u23ED";
8474
+ }
8475
+ if (stats.totalRuns === 0) return "-";
8476
+ const symbol = stats.failedRuns === 0 ? "\u2714" : stats.successfulRuns === 0 ? "\u2716" : "\u2714/\u2716";
8477
+ if (stats.totalRuns > 1) {
8478
+ if (stats.failedRuns > 0 && stats.successfulRuns > 0) {
8479
+ return `${symbol} ${stats.successfulRuns}/${stats.totalRuns}`;
8480
+ } else {
8481
+ return `${symbol} \xD7${stats.totalRuns}`;
8482
+ }
8483
+ }
8484
+ return symbol;
8485
+ }
8486
+ /**
8487
+ * Format the Details column for execution summary table
8488
+ */
8489
+ formatDetailsColumn(stats) {
8490
+ const parts = [];
8491
+ if (stats.outputsProduced && stats.outputsProduced > 0) {
8492
+ parts.push(`\u2192${stats.outputsProduced}`);
8493
+ }
8494
+ if (stats.issuesBySeverity.critical > 0) {
8495
+ parts.push(`${stats.issuesBySeverity.critical}\u{1F534}`);
8496
+ }
8497
+ if (stats.issuesBySeverity.warning > 0) {
8498
+ parts.push(`${stats.issuesBySeverity.warning}\u26A0\uFE0F`);
8499
+ }
8500
+ if (stats.issuesBySeverity.info > 0 && stats.issuesBySeverity.critical === 0 && stats.issuesBySeverity.warning === 0) {
8501
+ parts.push(`${stats.issuesBySeverity.info}\u{1F4A1}`);
8502
+ }
8503
+ if (stats.errorMessage) {
8504
+ parts.push(this.truncate(stats.errorMessage, 20));
8505
+ } else if (stats.skipCondition) {
8506
+ parts.push(this.truncate(stats.skipCondition, 20));
8507
+ }
8508
+ return parts.join(" ");
8509
+ }
8510
+ /**
8511
+ * Log the execution summary table
8512
+ */
8513
+ logExecutionSummary(stats) {
8514
+ const totalIssues = stats.checks.reduce((sum, s) => sum + s.issuesFound, 0);
8515
+ const criticalIssues = stats.checks.reduce((sum, s) => sum + s.issuesBySeverity.critical, 0);
8516
+ const warningIssues = stats.checks.reduce((sum, s) => sum + s.issuesBySeverity.warning, 0);
8517
+ const durationSec = (stats.totalDuration / 1e3).toFixed(1);
8518
+ const summaryTable = new (__require("cli-table3"))({
8519
+ style: {
8520
+ head: [],
8521
+ border: []
8522
+ },
8523
+ colWidths: [41]
8524
+ });
8525
+ summaryTable.push(
8526
+ [`Execution Complete (${durationSec}s)`],
8527
+ [`Checks: ${stats.totalChecksConfigured} configured \u2192 ${stats.totalExecutions} executions`],
8528
+ [
8529
+ `Status: ${stats.successfulExecutions} \u2714 \u2502 ${stats.failedExecutions} \u2716 \u2502 ${stats.skippedChecks} \u23ED`
8530
+ ]
8531
+ );
8532
+ if (totalIssues > 0) {
8533
+ let issuesLine = `Issues: ${totalIssues} total`;
8534
+ if (criticalIssues > 0) issuesLine += ` (${criticalIssues} \u{1F534}`;
8535
+ if (warningIssues > 0) issuesLine += `${criticalIssues > 0 ? " " : " ("}${warningIssues} \u26A0\uFE0F)`;
8536
+ else if (criticalIssues > 0) issuesLine += ")";
8537
+ summaryTable.push([issuesLine]);
8538
+ }
8539
+ logger.info("");
8540
+ logger.info(summaryTable.toString());
8541
+ logger.info("");
8542
+ logger.info("Check Details:");
8543
+ const detailsTable = new (__require("cli-table3"))({
8544
+ head: ["Check", "Duration", "Status", "Details"],
8545
+ colWidths: [21, 10, 10, 21],
8546
+ style: {
8547
+ head: ["cyan"],
8548
+ border: ["grey"]
8549
+ }
8550
+ });
8551
+ for (const checkStats of stats.checks) {
8552
+ const duration = checkStats.skipped ? "-" : `${(checkStats.totalDuration / 1e3).toFixed(1)}s`;
8553
+ const status = this.formatStatusColumn(checkStats);
8554
+ const details = this.formatDetailsColumn(checkStats);
8555
+ detailsTable.push([checkStats.checkName, duration, status, details]);
8556
+ }
8557
+ logger.info(detailsTable.toString());
8558
+ logger.info("");
8559
+ logger.info(
8560
+ "Legend: \u2714=success \u2502 \u2716=failed \u2502 \u23ED=skipped \u2502 \xD7N=iterations \u2502 \u2192N=outputs \u2502 N\u{1F534}=critical \u2502 N\u26A0\uFE0F=warnings"
8561
+ );
8562
+ }
8294
8563
  };
8295
8564
 
8296
8565
  export {
8297
8566
  CheckExecutionEngine
8298
8567
  };
8299
- //# sourceMappingURL=chunk-745RDQD3.mjs.map
8568
+ //# sourceMappingURL=chunk-NINHE4RF.mjs.map