@probelabs/visor 0.1.80 → 0.1.82

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
@@ -326,7 +326,9 @@ var init_session_registry = __esm({
326
326
  SessionRegistry = class _SessionRegistry {
327
327
  static instance;
328
328
  sessions = /* @__PURE__ */ new Map();
329
+ exitHandlerRegistered = false;
329
330
  constructor() {
331
+ this.registerExitHandlers();
330
332
  }
331
333
  /**
332
334
  * Get the singleton instance of SessionRegistry
@@ -360,7 +362,15 @@ var init_session_registry = __esm({
360
362
  unregisterSession(sessionId) {
361
363
  if (this.sessions.has(sessionId)) {
362
364
  console.error(`\u{1F5D1}\uFE0F Unregistering AI session: ${sessionId}`);
365
+ const agent = this.sessions.get(sessionId);
363
366
  this.sessions.delete(sessionId);
367
+ if (agent && typeof agent.cleanup === "function") {
368
+ try {
369
+ agent.cleanup();
370
+ } catch (error) {
371
+ console.error(`\u26A0\uFE0F Warning: Failed to cleanup ProbeAgent: ${error}`);
372
+ }
373
+ }
364
374
  }
365
375
  }
366
376
  /**
@@ -368,6 +378,14 @@ var init_session_registry = __esm({
368
378
  */
369
379
  clearAllSessions() {
370
380
  console.error(`\u{1F9F9} Clearing all AI sessions (${this.sessions.size} sessions)`);
381
+ for (const [, agent] of this.sessions.entries()) {
382
+ if (agent && typeof agent.cleanup === "function") {
383
+ try {
384
+ agent.cleanup();
385
+ } catch {
386
+ }
387
+ }
388
+ }
371
389
  this.sessions.clear();
372
390
  }
373
391
  /**
@@ -382,6 +400,44 @@ var init_session_registry = __esm({
382
400
  hasSession(sessionId) {
383
401
  return this.sessions.has(sessionId);
384
402
  }
403
+ /**
404
+ * Register process exit handlers to cleanup sessions on exit
405
+ */
406
+ registerExitHandlers() {
407
+ if (this.exitHandlerRegistered) {
408
+ return;
409
+ }
410
+ const cleanupAndExit = (signal) => {
411
+ if (this.sessions.size > 0) {
412
+ console.error(`
413
+ \u{1F9F9} [${signal}] Cleaning up ${this.sessions.size} active AI sessions...`);
414
+ this.clearAllSessions();
415
+ }
416
+ };
417
+ process.on("exit", () => {
418
+ if (this.sessions.size > 0) {
419
+ console.error(`\u{1F9F9} [exit] Cleaning up ${this.sessions.size} active AI sessions...`);
420
+ for (const [, agent] of this.sessions.entries()) {
421
+ if (agent && typeof agent.cleanup === "function") {
422
+ try {
423
+ agent.cleanup();
424
+ } catch {
425
+ }
426
+ }
427
+ }
428
+ this.sessions.clear();
429
+ }
430
+ });
431
+ process.on("SIGINT", () => {
432
+ cleanupAndExit("SIGINT");
433
+ process.exit(0);
434
+ });
435
+ process.on("SIGTERM", () => {
436
+ cleanupAndExit("SIGTERM");
437
+ process.exit(0);
438
+ });
439
+ this.exitHandlerRegistered = true;
440
+ }
385
441
  };
386
442
  }
387
443
  });
@@ -2283,20 +2339,6 @@ var init_liquid_extensions = __esm({
2283
2339
  }
2284
2340
  });
2285
2341
 
2286
- // src/providers/claude-code-types.ts
2287
- async function safeImport(moduleName) {
2288
- try {
2289
- return await import(moduleName);
2290
- } catch {
2291
- return null;
2292
- }
2293
- }
2294
- var init_claude_code_types = __esm({
2295
- "src/providers/claude-code-types.ts"() {
2296
- "use strict";
2297
- }
2298
- });
2299
-
2300
2342
  // src/providers/ai-check-provider.ts
2301
2343
  var import_promises2, import_path2, AICheckProvider;
2302
2344
  var init_ai_check_provider = __esm({
@@ -2309,7 +2351,6 @@ var init_ai_check_provider = __esm({
2309
2351
  init_liquid_extensions();
2310
2352
  import_promises2 = __toESM(require("fs/promises"));
2311
2353
  import_path2 = __toESM(require("path"));
2312
- init_claude_code_types();
2313
2354
  AICheckProvider = class extends CheckProvider {
2314
2355
  aiReviewService;
2315
2356
  liquidEngine;
@@ -2587,54 +2628,6 @@ var init_ai_check_provider = __esm({
2587
2628
  );
2588
2629
  }
2589
2630
  }
2590
- /**
2591
- * Setup MCP tools based on AI configuration
2592
- */
2593
- async setupMcpTools(aiConfig) {
2594
- const tools = [];
2595
- if (aiConfig.mcpServers) {
2596
- try {
2597
- const mcpModule = await safeImport("@modelcontextprotocol/sdk");
2598
- if (!mcpModule) {
2599
- console.warn("@modelcontextprotocol/sdk package not found. MCP servers disabled.");
2600
- return tools;
2601
- }
2602
- const createSdkMcpServer = mcpModule.createSdkMcpServer || mcpModule.default?.createSdkMcpServer;
2603
- if (typeof createSdkMcpServer === "function") {
2604
- for (const [serverName, serverConfig] of Object.entries(aiConfig.mcpServers)) {
2605
- try {
2606
- const server = await createSdkMcpServer({
2607
- name: serverName,
2608
- command: serverConfig.command,
2609
- args: serverConfig.args || [],
2610
- env: { ...process.env, ...serverConfig.env }
2611
- });
2612
- const serverTools = await server.listTools();
2613
- tools.push(
2614
- ...serverTools.map((tool) => ({
2615
- name: tool.name,
2616
- server: serverName
2617
- }))
2618
- );
2619
- } catch (serverError) {
2620
- console.warn(
2621
- `Failed to setup MCP server ${serverName}: ${serverError instanceof Error ? serverError.message : "Unknown error"}`
2622
- );
2623
- }
2624
- }
2625
- } else {
2626
- console.warn(
2627
- "createSdkMcpServer function not found in @modelcontextprotocol/sdk. MCP servers disabled."
2628
- );
2629
- }
2630
- } catch (error) {
2631
- console.warn(
2632
- `Failed to import MCP SDK: ${error instanceof Error ? error.message : "Unknown error"}. MCP servers disabled.`
2633
- );
2634
- }
2635
- }
2636
- return tools;
2637
- }
2638
2631
  async execute(prInfo, config, _dependencyResults, sessionInfo) {
2639
2632
  if (config.env) {
2640
2633
  const result = EnvironmentResolver.withTemporaryEnv(config.env, () => {
@@ -2691,11 +2684,9 @@ var init_ai_check_provider = __esm({
2691
2684
  }
2692
2685
  if (Object.keys(mcpServers).length > 0) {
2693
2686
  aiConfig.mcpServers = mcpServers;
2694
- const mcpConfig = { mcpServers };
2695
- const mcpTools = await this.setupMcpTools(mcpConfig);
2696
2687
  if (aiConfig.debug) {
2697
2688
  console.error(
2698
- `\u{1F527} Debug: AI check MCP configured with ${Object.keys(mcpServers).length} servers; discovered ${mcpTools.length} tools`
2689
+ `\u{1F527} Debug: AI check MCP configured with ${Object.keys(mcpServers).length} servers`
2699
2690
  );
2700
2691
  }
2701
2692
  }
@@ -3566,6 +3557,20 @@ var init_log_check_provider = __esm({
3566
3557
  }
3567
3558
  });
3568
3559
 
3560
+ // src/providers/claude-code-types.ts
3561
+ async function safeImport(moduleName) {
3562
+ try {
3563
+ return await import(moduleName);
3564
+ } catch {
3565
+ return null;
3566
+ }
3567
+ }
3568
+ var init_claude_code_types = __esm({
3569
+ "src/providers/claude-code-types.ts"() {
3570
+ "use strict";
3571
+ }
3572
+ });
3573
+
3569
3574
  // src/providers/claude-code-check-provider.ts
3570
3575
  function isClaudeCodeConstructor(value) {
3571
3576
  return typeof value === "function";
@@ -3679,59 +3684,6 @@ var init_claude_code_check_provider = __esm({
3679
3684
  );
3680
3685
  }
3681
3686
  }
3682
- /**
3683
- * Setup MCP tools based on configuration
3684
- */
3685
- async setupMcpTools(config) {
3686
- const tools = [];
3687
- if (config.allowedTools) {
3688
- for (const toolName of config.allowedTools) {
3689
- tools.push({ name: toolName });
3690
- }
3691
- }
3692
- if (config.mcpServers) {
3693
- try {
3694
- const mcpModule = await safeImport("@modelcontextprotocol/sdk");
3695
- if (!mcpModule) {
3696
- console.warn("@modelcontextprotocol/sdk package not found. MCP servers disabled.");
3697
- return tools;
3698
- }
3699
- const createSdkMcpServer = mcpModule.createSdkMcpServer || mcpModule.default?.createSdkMcpServer;
3700
- if (typeof createSdkMcpServer === "function") {
3701
- for (const [serverName, serverConfig] of Object.entries(config.mcpServers)) {
3702
- try {
3703
- const server = await createSdkMcpServer({
3704
- name: serverName,
3705
- command: serverConfig.command,
3706
- args: serverConfig.args || [],
3707
- env: { ...process.env, ...serverConfig.env }
3708
- });
3709
- const serverTools = await server.listTools();
3710
- tools.push(
3711
- ...serverTools.map((tool) => ({
3712
- name: tool.name,
3713
- server: serverName
3714
- }))
3715
- );
3716
- } catch (serverError) {
3717
- console.warn(
3718
- `Failed to setup MCP server ${serverName}: ${serverError instanceof Error ? serverError.message : "Unknown error"}`
3719
- );
3720
- }
3721
- }
3722
- } else {
3723
- console.warn(
3724
- "createSdkMcpServer function not found in @modelcontextprotocol/sdk. MCP servers disabled."
3725
- );
3726
- }
3727
- } catch (error) {
3728
- console.warn(
3729
- `Failed to import MCP SDK: ${error instanceof Error ? error.message : "Unknown error"}. MCP servers disabled.`
3730
- );
3731
- }
3732
- }
3733
- return tools;
3734
- }
3735
3687
  /**
3736
3688
  * Group files by their file extension for template context
3737
3689
  */
@@ -3962,14 +3914,18 @@ var init_claude_code_check_provider = __esm({
3962
3914
  const startTime = Date.now();
3963
3915
  try {
3964
3916
  const client = await this.initializeClaudeCodeClient();
3965
- const tools = await this.setupMcpTools(claudeCodeConfig);
3966
3917
  const query = {
3967
3918
  query: processedPrompt,
3968
- tools: tools.length > 0 ? tools : void 0,
3969
3919
  maxTurns: claudeCodeConfig.maxTurns || 5,
3970
3920
  systemPrompt: claudeCodeConfig.systemPrompt,
3971
3921
  subagent: claudeCodeConfig.subagent
3972
3922
  };
3923
+ if (claudeCodeConfig.allowedTools && claudeCodeConfig.allowedTools.length > 0) {
3924
+ query.tools = claudeCodeConfig.allowedTools.map((name) => ({ name }));
3925
+ }
3926
+ if (claudeCodeConfig.mcpServers && Object.keys(claudeCodeConfig.mcpServers).length > 0) {
3927
+ query.mcpServers = claudeCodeConfig.mcpServers;
3928
+ }
3973
3929
  let response;
3974
3930
  if (sessionInfo?.reuseSession && sessionInfo.parentSessionId) {
3975
3931
  response = await client.query({
@@ -3997,8 +3953,7 @@ var init_claude_code_check_provider = __esm({
3997
3953
  // Claude Code specific debug info
3998
3954
  sessionId: response.session_id,
3999
3955
  turnCount: response.turn_count,
4000
- usage: response.usage,
4001
- toolsUsed: tools.map((t) => t.name)
3956
+ usage: response.usage
4002
3957
  };
4003
3958
  const suppressionEnabled = config.suppressionEnabled !== false;
4004
3959
  const issueFilter = new IssueFilter(suppressionEnabled);
@@ -7369,172 +7324,187 @@ ${expr}
7369
7324
  let finalResult;
7370
7325
  if (isForEachDependent && forEachParentName) {
7371
7326
  this.recordForEachPreview(checkName, forEachItems);
7372
- if (debug) {
7373
- log2(
7374
- `\u{1F504} Debug: Check "${checkName}" depends on forEach check "${forEachParentName}", executing ${forEachItems.length} times`
7327
+ if (forEachItems.length === 0) {
7328
+ if (debug) {
7329
+ log2(
7330
+ `\u{1F504} Debug: Skipping check "${checkName}" - forEach check "${forEachParentName}" returned 0 items`
7331
+ );
7332
+ }
7333
+ logger.info(` forEach: no items from "${forEachParentName}", skipping check...`);
7334
+ finalResult = {
7335
+ issues: [],
7336
+ output: []
7337
+ };
7338
+ finalResult.isForEach = true;
7339
+ finalResult.forEachItems = [];
7340
+ } else {
7341
+ if (debug) {
7342
+ log2(
7343
+ `\u{1F504} Debug: Check "${checkName}" depends on forEach check "${forEachParentName}", executing ${forEachItems.length} times`
7344
+ );
7345
+ }
7346
+ logger.info(
7347
+ ` forEach: processing ${forEachItems.length} items from "${forEachParentName}"...`
7375
7348
  );
7376
- }
7377
- logger.info(
7378
- ` forEach: processing ${forEachItems.length} items from "${forEachParentName}"...`
7379
- );
7380
- const allIssues = [];
7381
- const allOutputs = [];
7382
- const aggregatedContents = [];
7383
- const itemTasks = forEachItems.map((item, itemIndex) => async () => {
7384
- const forEachDependencyResults = /* @__PURE__ */ new Map();
7385
- for (const [depName, depResult] of dependencyResults) {
7386
- if (forEachParents.includes(depName)) {
7387
- const depForEachResult = depResult;
7388
- if (Array.isArray(depForEachResult.output) && depForEachResult.output[itemIndex] !== void 0) {
7389
- const modifiedResult = {
7390
- issues: [],
7391
- output: depForEachResult.output[itemIndex]
7392
- };
7393
- forEachDependencyResults.set(depName, modifiedResult);
7394
- const rawResult = {
7395
- issues: [],
7396
- output: depForEachResult.output
7397
- };
7398
- forEachDependencyResults.set(`${depName}-raw`, rawResult);
7349
+ const allIssues = [];
7350
+ const allOutputs = [];
7351
+ const aggregatedContents = [];
7352
+ const itemTasks = forEachItems.map((item, itemIndex) => async () => {
7353
+ const forEachDependencyResults = /* @__PURE__ */ new Map();
7354
+ for (const [depName, depResult] of dependencyResults) {
7355
+ if (forEachParents.includes(depName)) {
7356
+ const depForEachResult = depResult;
7357
+ if (Array.isArray(depForEachResult.output) && depForEachResult.output[itemIndex] !== void 0) {
7358
+ const modifiedResult = {
7359
+ issues: [],
7360
+ output: depForEachResult.output[itemIndex]
7361
+ };
7362
+ forEachDependencyResults.set(depName, modifiedResult);
7363
+ const rawResult = {
7364
+ issues: [],
7365
+ output: depForEachResult.output
7366
+ };
7367
+ forEachDependencyResults.set(`${depName}-raw`, rawResult);
7368
+ } else {
7369
+ forEachDependencyResults.set(depName, depResult);
7370
+ }
7399
7371
  } else {
7400
7372
  forEachDependencyResults.set(depName, depResult);
7401
7373
  }
7402
- } else {
7403
- forEachDependencyResults.set(depName, depResult);
7404
7374
  }
7405
- }
7406
- if (checkConfig.if) {
7407
- const conditionResults = new Map(results);
7408
- for (const [depName, depResult] of forEachDependencyResults) {
7409
- conditionResults.set(depName, depResult);
7375
+ if (checkConfig.if) {
7376
+ const conditionResults = new Map(results);
7377
+ for (const [depName, depResult] of forEachDependencyResults) {
7378
+ conditionResults.set(depName, depResult);
7379
+ }
7380
+ const shouldRun = await this.evaluateCheckCondition(
7381
+ checkName,
7382
+ checkConfig.if,
7383
+ prInfo,
7384
+ conditionResults,
7385
+ debug
7386
+ );
7387
+ if (!shouldRun) {
7388
+ if (debug) {
7389
+ log2(
7390
+ `\u{1F504} Debug: Skipping forEach item ${itemIndex + 1} for check "${checkName}" (if condition evaluated to false)`
7391
+ );
7392
+ }
7393
+ return {
7394
+ index: itemIndex,
7395
+ itemResult: { issues: [] },
7396
+ skipped: true
7397
+ };
7398
+ }
7399
+ }
7400
+ if (debug) {
7401
+ log2(
7402
+ `\u{1F504} Debug: Executing check "${checkName}" for item ${itemIndex + 1}/${forEachItems.length}`
7403
+ );
7410
7404
  }
7411
- const shouldRun = await this.evaluateCheckCondition(
7405
+ const iterationStart = this.recordIterationStart(checkName);
7406
+ const itemResult = await this.executeWithRouting(
7412
7407
  checkName,
7413
- checkConfig.if,
7408
+ checkConfig,
7409
+ provider,
7410
+ providerConfig,
7414
7411
  prInfo,
7415
- conditionResults,
7416
- debug
7412
+ forEachDependencyResults,
7413
+ sessionInfo,
7414
+ config,
7415
+ dependencyGraph,
7416
+ debug,
7417
+ results,
7418
+ /*foreachContext*/
7419
+ {
7420
+ index: itemIndex,
7421
+ total: forEachItems.length,
7422
+ parent: forEachParentName
7423
+ }
7424
+ );
7425
+ const hadFatalError = (itemResult.issues || []).some((issue) => {
7426
+ const id = issue.ruleId || "";
7427
+ return id === "command/execution_error" || id.endsWith("/command/execution_error") || id === "command/transform_js_error" || id.endsWith("/command/transform_js_error") || id === "command/transform_error" || id.endsWith("/command/transform_error");
7428
+ });
7429
+ const iterationDuration = (Date.now() - iterationStart) / 1e3;
7430
+ this.recordIterationComplete(
7431
+ checkName,
7432
+ iterationStart,
7433
+ !hadFatalError,
7434
+ // Success if no fatal errors
7435
+ itemResult.issues || [],
7436
+ itemResult.output
7417
7437
  );
7418
- if (!shouldRun) {
7438
+ logger.info(
7439
+ ` \u2714 ${itemIndex + 1}/${forEachItems.length} (${iterationDuration.toFixed(1)}s)`
7440
+ );
7441
+ return { index: itemIndex, itemResult };
7442
+ });
7443
+ const forEachConcurrency = Math.max(
7444
+ 1,
7445
+ Math.min(forEachItems.length, effectiveMaxParallelism)
7446
+ );
7447
+ if (debug && forEachConcurrency > 1) {
7448
+ log2(
7449
+ `\u{1F504} Debug: Limiting forEach concurrency for check "${checkName}" to ${forEachConcurrency}`
7450
+ );
7451
+ }
7452
+ const forEachResults = await this.executeWithLimitedParallelism(
7453
+ itemTasks,
7454
+ forEachConcurrency,
7455
+ false
7456
+ );
7457
+ for (const result of forEachResults) {
7458
+ if (result.status === "rejected") {
7459
+ const error = result.reason;
7460
+ const errorMessage = error instanceof Error ? error.message : String(error);
7461
+ allIssues.push({
7462
+ ruleId: `${checkName}/forEach/iteration_error`,
7463
+ severity: "error",
7464
+ category: "logic",
7465
+ message: `forEach iteration failed: ${errorMessage}`,
7466
+ file: "",
7467
+ line: 0
7468
+ });
7419
7469
  if (debug) {
7420
7470
  log2(
7421
- `\u{1F504} Debug: Skipping forEach item ${itemIndex + 1} for check "${checkName}" (if condition evaluated to false)`
7471
+ `\u{1F504} Debug: forEach iteration for check "${checkName}" failed: ${errorMessage}`
7422
7472
  );
7423
7473
  }
7424
- return {
7425
- index: itemIndex,
7426
- itemResult: { issues: [] },
7427
- skipped: true
7428
- };
7474
+ continue;
7429
7475
  }
7430
- }
7431
- if (debug) {
7432
- log2(
7433
- `\u{1F504} Debug: Executing check "${checkName}" for item ${itemIndex + 1}/${forEachItems.length}`
7434
- );
7435
- }
7436
- const iterationStart = this.recordIterationStart(checkName);
7437
- const itemResult = await this.executeWithRouting(
7438
- checkName,
7439
- checkConfig,
7440
- provider,
7441
- providerConfig,
7442
- prInfo,
7443
- forEachDependencyResults,
7444
- sessionInfo,
7445
- config,
7446
- dependencyGraph,
7447
- debug,
7448
- results,
7449
- /*foreachContext*/
7450
- {
7451
- index: itemIndex,
7452
- total: forEachItems.length,
7453
- parent: forEachParentName
7476
+ if (result.value.skipped) {
7477
+ continue;
7454
7478
  }
7455
- );
7456
- const hadFatalError = (itemResult.issues || []).some((issue) => {
7457
- const id = issue.ruleId || "";
7458
- return id === "command/execution_error" || id.endsWith("/command/execution_error") || id === "command/transform_js_error" || id.endsWith("/command/transform_js_error") || id === "command/transform_error" || id.endsWith("/command/transform_error");
7459
- });
7460
- const iterationDuration = (Date.now() - iterationStart) / 1e3;
7461
- this.recordIterationComplete(
7462
- checkName,
7463
- iterationStart,
7464
- !hadFatalError,
7465
- // Success if no fatal errors
7466
- itemResult.issues || [],
7467
- itemResult.output
7468
- );
7469
- logger.info(
7470
- ` \u2714 ${itemIndex + 1}/${forEachItems.length} (${iterationDuration.toFixed(1)}s)`
7471
- );
7472
- return { index: itemIndex, itemResult };
7473
- });
7474
- const forEachConcurrency = Math.max(
7475
- 1,
7476
- Math.min(forEachItems.length, effectiveMaxParallelism)
7477
- );
7478
- if (debug && forEachConcurrency > 1) {
7479
- log2(
7480
- `\u{1F504} Debug: Limiting forEach concurrency for check "${checkName}" to ${forEachConcurrency}`
7481
- );
7482
- }
7483
- const forEachResults = await this.executeWithLimitedParallelism(
7484
- itemTasks,
7485
- forEachConcurrency,
7486
- false
7487
- );
7488
- for (const result of forEachResults) {
7489
- if (result.status === "rejected") {
7490
- const error = result.reason;
7491
- const errorMessage = error instanceof Error ? error.message : String(error);
7492
- allIssues.push({
7493
- ruleId: `${checkName}/forEach/iteration_error`,
7494
- severity: "error",
7495
- category: "logic",
7496
- message: `forEach iteration failed: ${errorMessage}`,
7497
- file: "",
7498
- line: 0
7499
- });
7500
- if (debug) {
7501
- log2(
7502
- `\u{1F504} Debug: forEach iteration for check "${checkName}" failed: ${errorMessage}`
7503
- );
7479
+ const { itemResult } = result.value;
7480
+ if (itemResult.issues) {
7481
+ allIssues.push(...itemResult.issues);
7482
+ }
7483
+ const resultWithOutput = itemResult;
7484
+ if (resultWithOutput.output !== void 0) {
7485
+ allOutputs.push(resultWithOutput.output);
7486
+ }
7487
+ const itemContent = resultWithOutput.content;
7488
+ if (typeof itemContent === "string" && itemContent.trim()) {
7489
+ aggregatedContents.push(itemContent.trim());
7504
7490
  }
7505
- continue;
7506
- }
7507
- if (result.value.skipped) {
7508
- continue;
7509
- }
7510
- const { itemResult } = result.value;
7511
- if (itemResult.issues) {
7512
- allIssues.push(...itemResult.issues);
7513
7491
  }
7514
- const resultWithOutput = itemResult;
7515
- if (resultWithOutput.output !== void 0) {
7516
- allOutputs.push(resultWithOutput.output);
7492
+ const finalOutput = allOutputs.length > 0 ? allOutputs : void 0;
7493
+ finalResult = {
7494
+ issues: allIssues,
7495
+ ...finalOutput !== void 0 ? { output: finalOutput } : {}
7496
+ };
7497
+ if (allOutputs.length > 0) {
7498
+ finalResult.isForEach = true;
7499
+ finalResult.forEachItems = allOutputs;
7517
7500
  }
7518
- const itemContent = resultWithOutput.content;
7519
- if (typeof itemContent === "string" && itemContent.trim()) {
7520
- aggregatedContents.push(itemContent.trim());
7501
+ if (aggregatedContents.length > 0) {
7502
+ finalResult.content = aggregatedContents.join("\n");
7521
7503
  }
7504
+ log2(
7505
+ `\u{1F504} Debug: Completed forEach execution for check "${checkName}", total issues: ${allIssues.length}`
7506
+ );
7522
7507
  }
7523
- const finalOutput = allOutputs.length > 0 ? allOutputs : void 0;
7524
- finalResult = {
7525
- issues: allIssues,
7526
- ...finalOutput !== void 0 ? { output: finalOutput } : {}
7527
- };
7528
- if (allOutputs.length > 0) {
7529
- finalResult.isForEach = true;
7530
- finalResult.forEachItems = allOutputs;
7531
- }
7532
- if (aggregatedContents.length > 0) {
7533
- finalResult.content = aggregatedContents.join("\n");
7534
- }
7535
- log2(
7536
- `\u{1F504} Debug: Completed forEach execution for check "${checkName}", total issues: ${allIssues.length}`
7537
- );
7538
7508
  } else {
7539
7509
  if (checkConfig.if) {
7540
7510
  const shouldRun = await this.evaluateCheckCondition(
@@ -7763,14 +7733,6 @@ ${expr}
7763
7733
  }
7764
7734
  }
7765
7735
  }
7766
- const executionStatistics = this.buildExecutionStatistics();
7767
- if (logFn === console.log) {
7768
- this.logExecutionSummary(executionStatistics);
7769
- }
7770
- if (shouldStopExecution) {
7771
- logger.info("");
7772
- logger.warn(`\u26A0\uFE0F Execution stopped early due to fail-fast`);
7773
- }
7774
7736
  if (debug) {
7775
7737
  if (shouldStopExecution) {
7776
7738
  log2(
@@ -7791,6 +7753,14 @@ ${expr}
7791
7753
  }
7792
7754
  }
7793
7755
  }
7756
+ const executionStatistics = this.buildExecutionStatistics();
7757
+ if (logFn === console.log) {
7758
+ this.logExecutionSummary(executionStatistics);
7759
+ }
7760
+ if (shouldStopExecution) {
7761
+ logger.info("");
7762
+ logger.warn(`\u26A0\uFE0F Execution stopped early due to fail-fast`);
7763
+ }
7794
7764
  return this.aggregateDependencyAwareResults(
7795
7765
  results,
7796
7766
  dependencyGraph,