@probelabs/visor 0.1.38 → 0.1.40

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/index.js CHANGED
@@ -93923,9 +93923,6 @@ class AIReviewService {
93923
93923
  category: 'logic',
93924
93924
  },
93925
93925
  ],
93926
- suggestions: [
93927
- 'Configure API keys in your GitHub repository secrets or environment variables',
93928
- ],
93929
93926
  debug: debugInfo,
93930
93927
  };
93931
93928
  }
@@ -93962,7 +93959,6 @@ class AIReviewService {
93962
93959
  category: 'logic',
93963
93960
  },
93964
93961
  ],
93965
- suggestions: ['Check AI service configuration and API key validity'],
93966
93962
  debug: debugInfo,
93967
93963
  };
93968
93964
  }
@@ -94034,9 +94030,6 @@ class AIReviewService {
94034
94030
  category: 'logic',
94035
94031
  },
94036
94032
  ],
94037
- suggestions: [
94038
- 'Check session reuse configuration and ensure parent check completed successfully',
94039
- ],
94040
94033
  debug: debugInfo,
94041
94034
  };
94042
94035
  }
@@ -94577,23 +94570,18 @@ ${prInfo.fullDiff ? this.escapeXml(prInfo.fullDiff) : ''}
94577
94570
  // Handle plain schema or no schema - no JSON parsing, return response as-is
94578
94571
  if (_schema === 'plain' || !_schema) {
94579
94572
  log(`📋 ${_schema === 'plain' ? 'Plain' : 'No'} schema detected - returning raw response without JSON parsing`);
94580
- // Strip common XML wrapper tags that AI might add when given XML-formatted prompts
94581
- let cleanedResponse = response.trim();
94582
- // Remove <result>...</result> tags if present
94583
- cleanedResponse = cleanedResponse
94584
- .replace(/^<result>\s*/i, '')
94585
- .replace(/\s*<\/result>$/i, '');
94586
- // Remove <response>...</response> tags if present
94587
- cleanedResponse = cleanedResponse
94588
- .replace(/^<response>\s*/i, '')
94589
- .replace(/\s*<\/response>$/i, '');
94590
- // Remove <answer>...</answer> tags if present
94591
- cleanedResponse = cleanedResponse
94592
- .replace(/^<answer>\s*/i, '')
94593
- .replace(/\s*<\/answer>$/i, '');
94573
+ // For plain schema, return the raw response as an issue
94594
94574
  return {
94595
- issues: [],
94596
- suggestions: [cleanedResponse.trim()],
94575
+ issues: [
94576
+ {
94577
+ file: 'AI_RESPONSE',
94578
+ line: 1,
94579
+ ruleId: 'ai/raw_response',
94580
+ message: response,
94581
+ severity: 'info',
94582
+ category: 'documentation',
94583
+ },
94584
+ ],
94597
94585
  debug: debugInfo,
94598
94586
  };
94599
94587
  }
@@ -94615,9 +94603,6 @@ ${prInfo.fullDiff ? this.escapeXml(prInfo.fullDiff) : ''}
94615
94603
  console.error('🚫 AI refused to analyze - returning empty result');
94616
94604
  return {
94617
94605
  issues: [],
94618
- suggestions: [
94619
- 'AI was unable to analyze this code. Please check the content or try again.',
94620
- ],
94621
94606
  };
94622
94607
  }
94623
94608
  // Try to extract JSON using improved method with proper bracket matching
@@ -94634,24 +94619,33 @@ ${prInfo.fullDiff ? this.escapeXml(prInfo.fullDiff) : ''}
94634
94619
  // Check if response is plain text and doesn't contain structured data
94635
94620
  if (!response.includes('{') && !response.includes('}')) {
94636
94621
  log('🔧 Plain text response detected, creating structured fallback...');
94637
- const isNoChanges = response.toLowerCase().includes('no') &&
94638
- (response.toLowerCase().includes('changes') ||
94639
- response.toLowerCase().includes('code'));
94640
94622
  reviewData = {
94641
- issues: [],
94642
- suggestions: isNoChanges
94643
- ? ['No code changes detected in this analysis']
94644
- : [
94645
- `AI response: ${response.substring(0, 200)}${response.length > 200 ? '...' : ''}`,
94646
- ],
94623
+ issues: [
94624
+ {
94625
+ file: 'AI_RESPONSE',
94626
+ line: 1,
94627
+ ruleId: 'ai/raw_response',
94628
+ message: response,
94629
+ severity: 'info',
94630
+ category: 'documentation',
94631
+ },
94632
+ ],
94647
94633
  };
94648
94634
  }
94649
94635
  else {
94650
- // Fallback: treat the entire response as a suggestion
94636
+ // Fallback: treat the entire response as an issue
94651
94637
  log('🔧 Creating fallback response from non-JSON content...');
94652
94638
  reviewData = {
94653
- issues: [],
94654
- suggestions: [response.trim()],
94639
+ issues: [
94640
+ {
94641
+ file: 'AI_RESPONSE',
94642
+ line: 1,
94643
+ ruleId: 'ai/raw_response',
94644
+ message: response,
94645
+ severity: 'info',
94646
+ category: 'documentation',
94647
+ },
94648
+ ],
94655
94649
  };
94656
94650
  }
94657
94651
  }
@@ -94660,8 +94654,16 @@ ${prInfo.fullDiff ? this.escapeXml(prInfo.fullDiff) : ''}
94660
94654
  // No JSON found at all - treat as plain text response
94661
94655
  log('🔧 No JSON found in response, treating as plain text...');
94662
94656
  reviewData = {
94663
- issues: [],
94664
- suggestions: [response.trim()],
94657
+ issues: [
94658
+ {
94659
+ file: 'AI_RESPONSE',
94660
+ line: 1,
94661
+ ruleId: 'ai/raw_response',
94662
+ message: response,
94663
+ severity: 'info',
94664
+ category: 'documentation',
94665
+ },
94666
+ ],
94665
94667
  };
94666
94668
  }
94667
94669
  }
@@ -94671,7 +94673,6 @@ ${prInfo.fullDiff ? this.escapeXml(prInfo.fullDiff) : ''}
94671
94673
  log(`📊 Overall score: ${0}`);
94672
94674
  log(`📋 Total issues: ${reviewData.issues?.length || 0}`);
94673
94675
  log(`🚨 Critical issues: ${reviewData.issues?.filter((i) => i.severity === 'critical').length || 0}`);
94674
- log(`💡 Suggestions count: ${Array.isArray(reviewData.suggestions) ? reviewData.suggestions.length : 0}`);
94675
94676
  log(`💬 Comments count: ${Array.isArray(reviewData.issues) ? reviewData.issues.length : 0}`);
94676
94677
  // Process issues from the simplified format
94677
94678
  const processedIssues = Array.isArray(reviewData.issues)
@@ -94693,7 +94694,6 @@ ${prInfo.fullDiff ? this.escapeXml(prInfo.fullDiff) : ''}
94693
94694
  // Validate and convert to ReviewSummary format
94694
94695
  const result = {
94695
94696
  issues: processedIssues,
94696
- suggestions: Array.isArray(reviewData.suggestions) ? reviewData.suggestions : [],
94697
94697
  };
94698
94698
  // Log issue counts
94699
94699
  const criticalCount = (result.issues || []).filter(i => i.severity === 'critical').length;
@@ -95395,12 +95395,9 @@ class CheckExecutionEngine {
95395
95395
  continue;
95396
95396
  // Extract issues for this check
95397
95397
  const checkIssues = (reviewSummary.issues || []).filter(issue => issue.ruleId?.startsWith(`${checkName}/`));
95398
- // Extract suggestions for this check
95399
- const checkSuggestions = (reviewSummary.suggestions || []).filter(suggestion => suggestion.startsWith(`[${checkName}]`));
95400
95398
  // Create a mini ReviewSummary for this check
95401
95399
  const checkSummary = {
95402
95400
  issues: checkIssues,
95403
- suggestions: checkSuggestions,
95404
95401
  debug: reviewSummary.debug,
95405
95402
  };
95406
95403
  // Render content for this check
@@ -95514,12 +95511,7 @@ class CheckExecutionEngine {
95514
95511
  }
95515
95512
  else if (schema === 'plain') {
95516
95513
  // Plain schema - return raw content directly
95517
- // Strip [checkName] prefixes from suggestions before joining
95518
- const cleanedSuggestions = (reviewSummary.suggestions || []).map(suggestion => {
95519
- // Remove [checkName] prefix if present
95520
- return suggestion.replace(/^\[[^\]]+\]\s*/, '');
95521
- });
95522
- return (reviewSummary.issues?.[0]?.message || '') + (cleanedSuggestions.join('\n\n') || '');
95514
+ return reviewSummary.issues?.[0]?.message || '';
95523
95515
  }
95524
95516
  else {
95525
95517
  // Use built-in schema template
@@ -95534,7 +95526,6 @@ class CheckExecutionEngine {
95534
95526
  const templateData = {
95535
95527
  issues: reviewSummary.issues || [],
95536
95528
  checkName: checkName,
95537
- suggestions: reviewSummary.suggestions || [],
95538
95529
  };
95539
95530
  const rendered = await liquid.parseAndRender(templateContent, templateData);
95540
95531
  return rendered.trim();
@@ -95597,7 +95588,6 @@ class CheckExecutionEngine {
95597
95588
  category: 'logic',
95598
95589
  },
95599
95590
  ],
95600
- suggestions: [],
95601
95591
  };
95602
95592
  }
95603
95593
  // Build dependency graph
@@ -95614,7 +95604,6 @@ class CheckExecutionEngine {
95614
95604
  category: 'logic',
95615
95605
  },
95616
95606
  ],
95617
- suggestions: [],
95618
95607
  };
95619
95608
  }
95620
95609
  // Log execution plan
@@ -95623,8 +95612,7 @@ class CheckExecutionEngine {
95623
95612
  // Execute checks level by level
95624
95613
  const results = new Map();
95625
95614
  const sessionRegistry = (__nccwpck_require__(46059).SessionRegistry).getInstance();
95626
- const provider = this.providerRegistry.getProviderOrThrow('ai');
95627
- this.setProviderWebhookContext(provider);
95615
+ // Note: We'll get the provider dynamically per check, not a single one for all
95628
95616
  const sessionIds = new Map(); // checkName -> sessionId
95629
95617
  let shouldStopExecution = false;
95630
95618
  for (let levelIndex = 0; levelIndex < dependencyGraph.executionOrder.length && !shouldStopExecution; levelIndex++) {
@@ -95668,20 +95656,28 @@ class CheckExecutionEngine {
95668
95656
  error: null,
95669
95657
  result: {
95670
95658
  issues: [],
95671
- suggestions: [`Check '${checkName}' was skipped - condition not met`],
95672
95659
  },
95673
95660
  };
95674
95661
  }
95675
95662
  }
95663
+ // Get the appropriate provider for this check type
95664
+ const providerType = checkConfig.type || 'ai';
95665
+ const provider = this.providerRegistry.getProviderOrThrow(providerType);
95666
+ this.setProviderWebhookContext(provider);
95676
95667
  // Create provider config for this specific check
95677
95668
  const providerConfig = {
95678
- type: 'ai',
95669
+ type: providerType,
95679
95670
  prompt: checkConfig.prompt,
95671
+ exec: checkConfig.exec,
95680
95672
  focus: checkConfig.focus || this.mapCheckNameToFocus(checkName),
95681
95673
  schema: checkConfig.schema,
95682
95674
  group: checkConfig.group,
95683
95675
  checkName: checkName, // Add checkName for sessionID
95684
95676
  eventContext: prInfo.eventContext, // Pass event context for templates
95677
+ transform: checkConfig.transform,
95678
+ level: checkConfig.level,
95679
+ message: checkConfig.message,
95680
+ env: checkConfig.env,
95685
95681
  ai: {
95686
95682
  timeout: timeout || 600000,
95687
95683
  debug: debug,
@@ -95690,9 +95686,19 @@ class CheckExecutionEngine {
95690
95686
  };
95691
95687
  // Pass results from dependencies if needed
95692
95688
  const dependencyResults = new Map();
95689
+ let isForEachDependent = false;
95690
+ let forEachItems = [];
95691
+ let forEachParentName;
95693
95692
  for (const depId of checkConfig.depends_on || []) {
95694
95693
  if (results.has(depId)) {
95695
- dependencyResults.set(depId, results.get(depId));
95694
+ const depResult = results.get(depId);
95695
+ dependencyResults.set(depId, depResult);
95696
+ // Check if this dependency has forEach enabled
95697
+ if (depResult.isForEach && depResult.forEachItems) {
95698
+ isForEachDependent = true;
95699
+ forEachItems = depResult.forEachItems;
95700
+ forEachParentName = depId;
95701
+ }
95696
95702
  }
95697
95703
  }
95698
95704
  // Determine if we should use session reuse
@@ -95721,10 +95727,54 @@ class CheckExecutionEngine {
95721
95727
  // Add session ID to provider config
95722
95728
  providerConfig.sessionId = currentSessionId;
95723
95729
  }
95724
- const result = await provider.execute(prInfo, providerConfig, dependencyResults, sessionInfo);
95725
- log(`🔧 Debug: Completed check: ${checkName}, issues found: ${(result.issues || []).length}`);
95730
+ // Handle forEach dependent execution
95731
+ let finalResult;
95732
+ if (isForEachDependent && forEachParentName) {
95733
+ log(`🔄 Debug: Check "${checkName}" depends on forEach check "${forEachParentName}", executing ${forEachItems.length} times`);
95734
+ const allIssues = [];
95735
+ const allOutputs = [];
95736
+ // Execute check for each item in the forEach array
95737
+ for (let itemIndex = 0; itemIndex < forEachItems.length; itemIndex++) {
95738
+ const item = forEachItems[itemIndex];
95739
+ // Create modified dependency results with current item
95740
+ const forEachDependencyResults = new Map();
95741
+ for (const [depName, depResult] of dependencyResults) {
95742
+ if (depName === forEachParentName) {
95743
+ // Replace the forEach parent's output with the current item
95744
+ const modifiedResult = {
95745
+ ...depResult,
95746
+ output: item,
95747
+ };
95748
+ forEachDependencyResults.set(depName, modifiedResult);
95749
+ }
95750
+ else {
95751
+ forEachDependencyResults.set(depName, depResult);
95752
+ }
95753
+ }
95754
+ log(`🔄 Debug: Executing check "${checkName}" for item ${itemIndex + 1}/${forEachItems.length}`);
95755
+ const itemResult = await provider.execute(prInfo, providerConfig, forEachDependencyResults, sessionInfo);
95756
+ // Collect issues from each iteration
95757
+ if (itemResult.issues) {
95758
+ allIssues.push(...itemResult.issues);
95759
+ }
95760
+ // Collect outputs from each iteration
95761
+ if (itemResult.output) {
95762
+ allOutputs.push(itemResult.output);
95763
+ }
95764
+ }
95765
+ finalResult = {
95766
+ issues: allIssues,
95767
+ output: allOutputs.length > 0 ? allOutputs : undefined,
95768
+ };
95769
+ log(`🔄 Debug: Completed forEach execution for check "${checkName}", total issues: ${allIssues.length}`);
95770
+ }
95771
+ else {
95772
+ // Normal single execution
95773
+ finalResult = await provider.execute(prInfo, providerConfig, dependencyResults, sessionInfo);
95774
+ log(`🔧 Debug: Completed check: ${checkName}, issues found: ${(finalResult.issues || []).length}`);
95775
+ }
95726
95776
  // Add group, schema, template info and timestamp to issues from config
95727
- const enrichedIssues = (result.issues || []).map(issue => ({
95777
+ const enrichedIssues = (finalResult.issues || []).map(issue => ({
95728
95778
  ...issue,
95729
95779
  ruleId: `${checkName}/${issue.ruleId}`,
95730
95780
  group: checkConfig.group,
@@ -95733,7 +95783,7 @@ class CheckExecutionEngine {
95733
95783
  timestamp: Date.now(),
95734
95784
  }));
95735
95785
  const enrichedResult = {
95736
- ...result,
95786
+ ...finalResult,
95737
95787
  issues: enrichedIssues,
95738
95788
  };
95739
95789
  return {
@@ -95758,8 +95808,34 @@ class CheckExecutionEngine {
95758
95808
  for (let i = 0; i < levelResults.length; i++) {
95759
95809
  const checkName = executionGroup.parallel[i];
95760
95810
  const result = levelResults[i];
95811
+ const checkConfig = config.checks[checkName];
95761
95812
  if (result.status === 'fulfilled' && result.value.result && !result.value.error) {
95762
- results.set(checkName, result.value.result);
95813
+ const reviewResult = result.value.result;
95814
+ // Handle forEach logic - process array outputs
95815
+ if (checkConfig?.forEach && reviewResult.output) {
95816
+ let outputArray = reviewResult.output;
95817
+ // Ensure output is an array
95818
+ if (!Array.isArray(outputArray)) {
95819
+ // Try to parse as JSON if it's a string
95820
+ if (typeof outputArray === 'string') {
95821
+ try {
95822
+ const parsed = JSON.parse(outputArray);
95823
+ outputArray = Array.isArray(parsed) ? parsed : [parsed];
95824
+ }
95825
+ catch {
95826
+ outputArray = [outputArray];
95827
+ }
95828
+ }
95829
+ else {
95830
+ outputArray = [outputArray];
95831
+ }
95832
+ }
95833
+ log(`🔄 Debug: Check "${checkName}" has forEach enabled, processing ${outputArray.length} items`);
95834
+ // Store the array for iteration by dependent checks
95835
+ reviewResult.forEachItems = outputArray;
95836
+ reviewResult.isForEach = true;
95837
+ }
95838
+ results.set(checkName, reviewResult);
95763
95839
  }
95764
95840
  else {
95765
95841
  // Store error result for dependency tracking
@@ -95781,7 +95857,6 @@ class CheckExecutionEngine {
95781
95857
  replacement: undefined,
95782
95858
  },
95783
95859
  ],
95784
- suggestions: [],
95785
95860
  };
95786
95861
  results.set(checkName, errorSummary);
95787
95862
  // Check if we should stop execution due to fail-fast
@@ -95879,7 +95954,6 @@ class CheckExecutionEngine {
95879
95954
  error: null,
95880
95955
  result: {
95881
95956
  issues: [],
95882
- suggestions: [`Check '${checkName}' was skipped - condition not met`],
95883
95957
  },
95884
95958
  };
95885
95959
  }
@@ -96001,7 +96075,6 @@ class CheckExecutionEngine {
96001
96075
  */
96002
96076
  aggregateDependencyAwareResults(results, dependencyGraph, debug, stoppedEarly) {
96003
96077
  const aggregatedIssues = [];
96004
- const aggregatedSuggestions = [];
96005
96078
  const debugInfo = [];
96006
96079
  // Add execution plan info
96007
96080
  const stats = dependency_resolver_1.DependencyResolver.getExecutionStats(dependencyGraph);
@@ -96035,13 +96108,8 @@ class CheckExecutionEngine {
96035
96108
  }
96036
96109
  // Issues are already prefixed and enriched with group/schema info
96037
96110
  aggregatedIssues.push(...(result.issues || []));
96038
- // Add suggestions with check name prefix
96039
- const prefixedSuggestions = (result.suggestions || []).map(suggestion => `[${checkName}] ${suggestion}`);
96040
- aggregatedSuggestions.push(...prefixedSuggestions);
96041
96111
  }
96042
96112
  }
96043
- // Add summary information
96044
- aggregatedSuggestions.unshift(...debugInfo);
96045
96113
  console.error(`🔧 Debug: Aggregated ${aggregatedIssues.length} issues from ${results.size} dependency-aware checks`);
96046
96114
  // Apply issue suppression filtering
96047
96115
  const suppressionEnabled = this.config?.output?.suppressionEnabled !== false;
@@ -96086,25 +96154,20 @@ class CheckExecutionEngine {
96086
96154
  }
96087
96155
  return {
96088
96156
  issues: filteredIssues,
96089
- suggestions: aggregatedSuggestions,
96090
96157
  debug: aggregatedDebug,
96091
96158
  };
96092
96159
  }
96093
96160
  /**
96094
96161
  * Aggregate results from parallel check execution (legacy method)
96095
96162
  */
96096
- aggregateParallelResults(results, checkNames, debug, stoppedEarly) {
96163
+ aggregateParallelResults(results, checkNames, debug, _stoppedEarly) {
96097
96164
  const aggregatedIssues = [];
96098
- const aggregatedSuggestions = [];
96099
96165
  const debugInfo = [];
96100
- let successfulChecks = 0;
96101
- let failedChecks = 0;
96102
96166
  results.forEach((result, index) => {
96103
96167
  const checkName = checkNames[index];
96104
96168
  if (result.status === 'fulfilled') {
96105
96169
  const checkResult = result.value;
96106
96170
  if (checkResult.error) {
96107
- failedChecks++;
96108
96171
  const log = console.error;
96109
96172
  log(`🔧 Debug: Check ${checkName} failed: ${checkResult.error}`);
96110
96173
  debugInfo.push(`❌ Check "${checkName}" failed: ${checkResult.error}`);
@@ -96130,18 +96193,13 @@ class CheckExecutionEngine {
96130
96193
  });
96131
96194
  }
96132
96195
  else if (checkResult.result) {
96133
- successfulChecks++;
96134
96196
  console.error(`🔧 Debug: Check ${checkName} succeeded with ${(checkResult.result.issues || []).length} issues`);
96135
96197
  debugInfo.push(`✅ Check "${checkName}" completed: ${(checkResult.result.issues || []).length} issues found`);
96136
96198
  // Issues are already prefixed and enriched with group/schema info
96137
96199
  aggregatedIssues.push(...(checkResult.result.issues || []));
96138
- // Add suggestions with check name prefix
96139
- const prefixedSuggestions = (checkResult.result.suggestions || []).map(suggestion => `[${checkName}] ${suggestion}`);
96140
- aggregatedSuggestions.push(...prefixedSuggestions);
96141
96200
  }
96142
96201
  }
96143
96202
  else {
96144
- failedChecks++;
96145
96203
  const errorMessage = result.reason instanceof Error ? result.reason.message : String(result.reason);
96146
96204
  const log = console.error;
96147
96205
  log(`🔧 Debug: Check ${checkName} promise rejected: ${errorMessage}`);
@@ -96167,11 +96225,6 @@ class CheckExecutionEngine {
96167
96225
  });
96168
96226
  }
96169
96227
  });
96170
- // Add summary information
96171
- debugInfo.unshift(stoppedEarly
96172
- ? `🛑 Parallel execution stopped early (fail-fast): ${successfulChecks} successful, ${failedChecks} failed`
96173
- : `🔍 Parallel execution completed: ${successfulChecks} successful, ${failedChecks} failed`);
96174
- aggregatedSuggestions.unshift(...debugInfo);
96175
96228
  console.error(`🔧 Debug: Aggregated ${aggregatedIssues.length} issues from ${results.length} checks`);
96176
96229
  // Apply issue suppression filtering
96177
96230
  const suppressionEnabled = this.config?.output?.suppressionEnabled !== false;
@@ -96273,7 +96326,6 @@ class CheckExecutionEngine {
96273
96326
  }
96274
96327
  return {
96275
96328
  issues: filteredIssues,
96276
- suggestions: aggregatedSuggestions,
96277
96329
  debug: aggregatedDebug,
96278
96330
  };
96279
96331
  }
@@ -96384,7 +96436,6 @@ class CheckExecutionEngine {
96384
96436
  replacement: undefined,
96385
96437
  },
96386
96438
  ],
96387
- suggestions: [`Error: ${errorMessage}`],
96388
96439
  },
96389
96440
  executionTime,
96390
96441
  timestamp,
@@ -96599,7 +96650,7 @@ class CheckExecutionEngine {
96599
96650
  try {
96600
96651
  const checkIssues = issuesByCheck.get(checkName) || [];
96601
96652
  // Evaluate failure conditions for this specific check
96602
- const failureResults = await this.evaluateFailureConditions(checkName, { issues: checkIssues, suggestions: [] }, options.config);
96653
+ const failureResults = await this.evaluateFailureConditions(checkName, { issues: checkIssues }, options.config);
96603
96654
  await this.githubCheckService.completeCheckRun(options.githubChecks.owner, options.githubChecks.repo, checkRun.id, checkName, failureResults, checkIssues);
96604
96655
  console.log(`✅ Completed ${checkName} check with ${checkIssues.length} issues`);
96605
96656
  }
@@ -96875,7 +96926,6 @@ async function main() {
96875
96926
  issues: Object.values(groupedResults)
96876
96927
  .flatMap((r) => r.map((check) => check.issues || []).flat())
96877
96928
  .flat(),
96878
- suggestions: [],
96879
96929
  },
96880
96930
  executionTime: 0,
96881
96931
  timestamp: new Date().toISOString(),
@@ -96891,7 +96941,6 @@ async function main() {
96891
96941
  issues: Object.values(groupedResults)
96892
96942
  .flatMap((r) => r.map((check) => check.issues || []).flat())
96893
96943
  .flat(),
96894
- suggestions: [], // Suggestions are now embedded in issues
96895
96944
  },
96896
96945
  executionTime: 0,
96897
96946
  timestamp: new Date().toISOString(),
@@ -96907,7 +96956,6 @@ async function main() {
96907
96956
  issues: Object.values(groupedResults)
96908
96957
  .flatMap((r) => r.map((check) => check.issues || []).flat())
96909
96958
  .flat(),
96910
- suggestions: [], // Suggestions are now embedded in issues
96911
96959
  },
96912
96960
  executionTime: 0,
96913
96961
  timestamp: new Date().toISOString(),
@@ -97355,7 +97403,7 @@ class ConfigManager {
97355
97403
  validCheckTypes = [
97356
97404
  'ai',
97357
97405
  'claude-code',
97358
- 'tool',
97406
+ 'command',
97359
97407
  'http',
97360
97408
  'http_input',
97361
97409
  'http_client',
@@ -97701,11 +97749,11 @@ class ConfigManager {
97701
97749
  message: `Invalid check configuration for "${checkName}": missing prompt (required for AI checks)`,
97702
97750
  });
97703
97751
  }
97704
- // Tool checks require exec field
97705
- if (checkConfig.type === 'tool' && !checkConfig.exec) {
97752
+ // Command checks require exec field
97753
+ if (checkConfig.type === 'command' && !checkConfig.exec) {
97706
97754
  errors.push({
97707
97755
  field: `checks.${checkName}.exec`,
97708
- message: `Invalid check configuration for "${checkName}": missing exec field (required for tool checks)`,
97756
+ message: `Invalid check configuration for "${checkName}": missing exec field (required for command checks)`,
97709
97757
  });
97710
97758
  }
97711
97759
  // HTTP output checks require url and body fields
@@ -98331,7 +98379,6 @@ class FailureConditionEvaluator {
98331
98379
  // Required output property (empty for if conditions)
98332
98380
  output: {
98333
98381
  issues: [],
98334
- suggestions: [],
98335
98382
  },
98336
98383
  // Utility metadata
98337
98384
  metadata: {
@@ -98473,7 +98520,7 @@ class FailureConditionEvaluator {
98473
98520
  // Extract context variables
98474
98521
  const output = context.output || {};
98475
98522
  const issues = output.issues || [];
98476
- const suggestions = output.suggestions || [];
98523
+ const suggestions = [];
98477
98524
  // Backward compatibility: provide metadata for transition period
98478
98525
  // TODO: Remove after all configurations are updated
98479
98526
  const metadata = context.metadata || {
@@ -98584,7 +98631,7 @@ class FailureConditionEvaluator {
98584
98631
  * Build the evaluation context for expressions
98585
98632
  */
98586
98633
  buildEvaluationContext(checkName, checkSchema, checkGroup, reviewSummary, previousOutputs) {
98587
- const { issues, suggestions, debug } = reviewSummary;
98634
+ const { issues, debug } = reviewSummary;
98588
98635
  const context = {
98589
98636
  output: {
98590
98637
  issues: (issues || []).map(issue => ({
@@ -98600,7 +98647,6 @@ class FailureConditionEvaluator {
98600
98647
  suggestion: issue.suggestion,
98601
98648
  replacement: issue.replacement,
98602
98649
  })),
98603
- suggestions,
98604
98650
  // Include additional schema-specific data from reviewSummary
98605
98651
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
98606
98652
  ...reviewSummary, // Pass through any additional fields
@@ -100743,7 +100789,6 @@ async function completeIndividualChecks(checkService, owner, repo, checkRunMap,
100743
100789
  // Create a ReviewSummary for this check's issues
100744
100790
  const checkReviewSummary = {
100745
100791
  issues: checkIssues,
100746
- suggestions: [],
100747
100792
  };
100748
100793
  // Determine which fail_if to use: check-specific overrides global
100749
100794
  const effectiveFailIf = checkFailIf || globalFailIf;
@@ -100791,7 +100836,6 @@ async function completeCombinedCheck(checkService, owner, repo, checkRunMap, gro
100791
100836
  // Create a combined ReviewSummary with all issues
100792
100837
  const combinedReviewSummary = {
100793
100838
  issues: allIssues,
100794
- suggestions: [],
100795
100839
  };
100796
100840
  // Evaluate global fail_if for the combined check
100797
100841
  const globalFailIf = config?.fail_if;
@@ -101137,22 +101181,6 @@ class OutputFormatters {
101137
101181
  else {
101138
101182
  output += 'No issues found!\n\n';
101139
101183
  }
101140
- // Suggestions table
101141
- if ((result.reviewSummary.suggestions || []).length > 0) {
101142
- const suggestionsTable = new cli_table3_1.default({
101143
- head: ['#', 'Suggestion'],
101144
- colWidths: [5, 70],
101145
- style: {
101146
- head: ['cyan', 'bold'],
101147
- border: ['grey'],
101148
- },
101149
- });
101150
- output += 'Suggestions\n';
101151
- (result.reviewSummary.suggestions || []).forEach((suggestion, index) => {
101152
- suggestionsTable.push([(index + 1).toString(), this.wrapText(suggestion, 65)]);
101153
- });
101154
- output += suggestionsTable.toString() + '\n\n';
101155
- }
101156
101184
  // Files table (if requested)
101157
101185
  if (options.includeFiles && result.repositoryInfo.files.length > 0) {
101158
101186
  const filesTable = new cli_table3_1.default({
@@ -101210,7 +101238,6 @@ class OutputFormatters {
101210
101238
  issues: options.groupByCategory
101211
101239
  ? this.groupCommentsByCategory((0, reviewer_1.convertIssuesToComments)(issues || []))
101212
101240
  : issues || [],
101213
- suggestions: result.reviewSummary.suggestions || [],
101214
101241
  files: options.includeFiles ? result.repositoryInfo.files : undefined,
101215
101242
  debug: result.debug, // Include debug information when available
101216
101243
  failureConditions: result.failureConditions || [], // Include failure condition results
@@ -101507,14 +101534,6 @@ class OutputFormatters {
101507
101534
  output += `## No Issues Found\n\n`;
101508
101535
  output += `Great job! No issues were detected in the analyzed code.\n\n`;
101509
101536
  }
101510
- // Suggestions
101511
- if ((result.reviewSummary.suggestions || []).length > 0) {
101512
- output += `## Recommendations\n\n`;
101513
- (result.reviewSummary.suggestions || []).forEach((suggestion, index) => {
101514
- output += `${index + 1}. ${suggestion}\n`;
101515
- });
101516
- output += '\n';
101517
- }
101518
101537
  // Files (if requested)
101519
101538
  if (options.includeFiles && result.repositoryInfo.files.length > 0) {
101520
101539
  output += `## Files Changed\n\n`;
@@ -102196,9 +102215,8 @@ class AICheckProvider extends check_provider_interface_1.CheckProvider {
102196
102215
  styleIssues: result.issues?.filter(i => i.category === 'style') || [],
102197
102216
  logicIssues: result.issues?.filter(i => i.category === 'logic') || [],
102198
102217
  documentationIssues: result.issues?.filter(i => i.category === 'documentation') || [],
102199
- // All issues and suggestions
102218
+ // All issues
102200
102219
  issues: result.issues || [],
102201
- suggestions: result.suggestions || [],
102202
102220
  // Debug information if available
102203
102221
  debug: result.debug,
102204
102222
  // Raw data for advanced use
@@ -102437,13 +102455,13 @@ exports.AICheckProvider = AICheckProvider;
102437
102455
  Object.defineProperty(exports, "__esModule", ({ value: true }));
102438
102456
  exports.CheckProviderRegistry = void 0;
102439
102457
  const ai_check_provider_1 = __nccwpck_require__(98901);
102440
- const tool_check_provider_1 = __nccwpck_require__(70477);
102441
102458
  const http_check_provider_1 = __nccwpck_require__(31115);
102442
102459
  const http_input_provider_1 = __nccwpck_require__(74423);
102443
102460
  const http_client_provider_1 = __nccwpck_require__(36270);
102444
102461
  const noop_check_provider_1 = __nccwpck_require__(53003);
102445
102462
  const log_check_provider_1 = __nccwpck_require__(24903);
102446
102463
  const claude_code_check_provider_1 = __nccwpck_require__(17985);
102464
+ const command_check_provider_1 = __nccwpck_require__(11878);
102447
102465
  /**
102448
102466
  * Registry for managing check providers
102449
102467
  */
@@ -102469,7 +102487,7 @@ class CheckProviderRegistry {
102469
102487
  registerDefaultProviders() {
102470
102488
  // Register all built-in providers
102471
102489
  this.register(new ai_check_provider_1.AICheckProvider());
102472
- this.register(new tool_check_provider_1.ToolCheckProvider());
102490
+ this.register(new command_check_provider_1.CommandCheckProvider());
102473
102491
  this.register(new http_check_provider_1.HttpCheckProvider());
102474
102492
  this.register(new http_input_provider_1.HttpInputProvider());
102475
102493
  this.register(new http_client_provider_1.HttpClientProvider());
@@ -103008,7 +103026,6 @@ class ClaudeCodeCheckProvider extends check_provider_interface_1.CheckProvider {
103008
103026
  documentationIssues: result.issues?.filter(i => i.category === 'documentation') || [],
103009
103027
  // All issues and suggestions
103010
103028
  issues: result.issues || [],
103011
- suggestions: result.suggestions || [],
103012
103029
  // Debug information if available
103013
103030
  debug: result.debug,
103014
103031
  // Raw data for advanced use
@@ -103034,14 +103051,12 @@ class ClaudeCodeCheckProvider extends check_provider_interface_1.CheckProvider {
103034
103051
  // Convert to ReviewSummary format
103035
103052
  return {
103036
103053
  issues: parsed.issues || [],
103037
- suggestions: parsed.suggestions || [],
103038
103054
  };
103039
103055
  }
103040
103056
  catch {
103041
103057
  // If not JSON, treat as plain text comment
103042
103058
  return {
103043
103059
  issues: [],
103044
- suggestions: [],
103045
103060
  };
103046
103061
  }
103047
103062
  }
@@ -103256,6 +103271,244 @@ async function safeImport(moduleName) {
103256
103271
  }
103257
103272
 
103258
103273
 
103274
+ /***/ }),
103275
+
103276
+ /***/ 11878:
103277
+ /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
103278
+
103279
+ "use strict";
103280
+
103281
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
103282
+ if (k2 === undefined) k2 = k;
103283
+ var desc = Object.getOwnPropertyDescriptor(m, k);
103284
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
103285
+ desc = { enumerable: true, get: function() { return m[k]; } };
103286
+ }
103287
+ Object.defineProperty(o, k2, desc);
103288
+ }) : (function(o, m, k, k2) {
103289
+ if (k2 === undefined) k2 = k;
103290
+ o[k2] = m[k];
103291
+ }));
103292
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
103293
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
103294
+ }) : function(o, v) {
103295
+ o["default"] = v;
103296
+ });
103297
+ var __importStar = (this && this.__importStar) || (function () {
103298
+ var ownKeys = function(o) {
103299
+ ownKeys = Object.getOwnPropertyNames || function (o) {
103300
+ var ar = [];
103301
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
103302
+ return ar;
103303
+ };
103304
+ return ownKeys(o);
103305
+ };
103306
+ return function (mod) {
103307
+ if (mod && mod.__esModule) return mod;
103308
+ var result = {};
103309
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
103310
+ __setModuleDefault(result, mod);
103311
+ return result;
103312
+ };
103313
+ })();
103314
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
103315
+ exports.CommandCheckProvider = void 0;
103316
+ const check_provider_interface_1 = __nccwpck_require__(14131);
103317
+ const liquidjs_1 = __nccwpck_require__(48694);
103318
+ /**
103319
+ * Check provider that executes shell commands and captures their output
103320
+ * Supports JSON parsing and integration with forEach functionality
103321
+ */
103322
+ class CommandCheckProvider extends check_provider_interface_1.CheckProvider {
103323
+ liquid;
103324
+ constructor() {
103325
+ super();
103326
+ this.liquid = new liquidjs_1.Liquid({
103327
+ cache: false,
103328
+ strictFilters: false,
103329
+ strictVariables: false,
103330
+ });
103331
+ }
103332
+ getName() {
103333
+ return 'command';
103334
+ }
103335
+ getDescription() {
103336
+ return 'Execute shell commands and capture output for processing';
103337
+ }
103338
+ async validateConfig(config) {
103339
+ if (!config || typeof config !== 'object') {
103340
+ return false;
103341
+ }
103342
+ const cfg = config;
103343
+ // Must have exec specified
103344
+ if (!cfg.exec || typeof cfg.exec !== 'string') {
103345
+ return false;
103346
+ }
103347
+ return true;
103348
+ }
103349
+ async execute(prInfo, config, dependencyResults) {
103350
+ const command = config.exec;
103351
+ const transform = config.transform;
103352
+ // Prepare template context for Liquid rendering
103353
+ const templateContext = {
103354
+ pr: {
103355
+ number: prInfo.number,
103356
+ title: prInfo.title,
103357
+ author: prInfo.author,
103358
+ branch: prInfo.head,
103359
+ base: prInfo.base,
103360
+ },
103361
+ files: prInfo.files,
103362
+ fileCount: prInfo.files.length,
103363
+ outputs: this.buildOutputContext(dependencyResults),
103364
+ env: this.getSafeEnvironmentVariables(),
103365
+ };
103366
+ try {
103367
+ // Render the command with Liquid templates if needed
103368
+ let renderedCommand = command;
103369
+ if (command.includes('{{') || command.includes('{%')) {
103370
+ renderedCommand = await this.liquid.parseAndRender(command, templateContext);
103371
+ }
103372
+ // Prepare environment variables - convert all to strings
103373
+ const scriptEnv = {};
103374
+ for (const [key, value] of Object.entries(process.env)) {
103375
+ if (value !== undefined) {
103376
+ scriptEnv[key] = value;
103377
+ }
103378
+ }
103379
+ if (config.env) {
103380
+ for (const [key, value] of Object.entries(config.env)) {
103381
+ if (value !== undefined && value !== null) {
103382
+ scriptEnv[key] = String(value);
103383
+ }
103384
+ }
103385
+ }
103386
+ // Execute the script using dynamic import to avoid Jest issues
103387
+ const { exec } = await Promise.resolve().then(() => __importStar(__nccwpck_require__(35317)));
103388
+ const { promisify } = await Promise.resolve().then(() => __importStar(__nccwpck_require__(39023)));
103389
+ const execAsync = promisify(exec);
103390
+ const { stdout, stderr } = await execAsync(renderedCommand, {
103391
+ env: scriptEnv,
103392
+ timeout: 60000, // 60 second timeout
103393
+ maxBuffer: 10 * 1024 * 1024, // 10MB buffer
103394
+ });
103395
+ if (stderr && process.env.DEBUG) {
103396
+ console.error(`Command stderr: ${stderr}`);
103397
+ }
103398
+ // Try to parse output as JSON
103399
+ let output = stdout.trim();
103400
+ try {
103401
+ // Attempt to parse as JSON
103402
+ const parsed = JSON.parse(stdout.trim());
103403
+ output = parsed;
103404
+ }
103405
+ catch {
103406
+ // If not JSON, keep as string
103407
+ output = stdout.trim();
103408
+ }
103409
+ // Apply transform if specified
103410
+ let finalOutput = output;
103411
+ if (transform) {
103412
+ try {
103413
+ const transformContext = {
103414
+ ...templateContext,
103415
+ output,
103416
+ };
103417
+ const rendered = await this.liquid.parseAndRender(transform, transformContext);
103418
+ // Try to parse the transformed result as JSON
103419
+ try {
103420
+ finalOutput = JSON.parse(rendered.trim());
103421
+ }
103422
+ catch {
103423
+ finalOutput = rendered.trim();
103424
+ }
103425
+ }
103426
+ catch (error) {
103427
+ return {
103428
+ issues: [
103429
+ {
103430
+ file: 'command',
103431
+ line: 0,
103432
+ ruleId: 'command/transform_error',
103433
+ message: `Failed to apply transform: ${error instanceof Error ? error.message : 'Unknown error'}`,
103434
+ severity: 'error',
103435
+ category: 'logic',
103436
+ },
103437
+ ],
103438
+ };
103439
+ }
103440
+ }
103441
+ // Return the output as part of the review summary
103442
+ // The output will be available to dependent checks
103443
+ return {
103444
+ issues: [],
103445
+ output: finalOutput,
103446
+ };
103447
+ }
103448
+ catch (error) {
103449
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
103450
+ return {
103451
+ issues: [
103452
+ {
103453
+ file: 'command',
103454
+ line: 0,
103455
+ ruleId: 'command/execution_error',
103456
+ message: `Command execution failed: ${errorMessage}`,
103457
+ severity: 'error',
103458
+ category: 'logic',
103459
+ },
103460
+ ],
103461
+ };
103462
+ }
103463
+ }
103464
+ buildOutputContext(dependencyResults) {
103465
+ if (!dependencyResults) {
103466
+ return {};
103467
+ }
103468
+ const outputs = {};
103469
+ for (const [checkName, result] of dependencyResults) {
103470
+ if (result.output !== undefined) {
103471
+ outputs[checkName] = result.output;
103472
+ }
103473
+ else {
103474
+ outputs[checkName] = {
103475
+ issueCount: result.issues?.length || 0,
103476
+ issues: result.issues || [],
103477
+ };
103478
+ }
103479
+ }
103480
+ return outputs;
103481
+ }
103482
+ getSafeEnvironmentVariables() {
103483
+ const safeVars = {};
103484
+ const allowedPrefixes = ['CI_', 'GITHUB_', 'RUNNER_', 'NODE_', 'npm_', 'PATH', 'HOME', 'USER'];
103485
+ for (const [key, value] of Object.entries(process.env)) {
103486
+ if (value !== undefined && allowedPrefixes.some(prefix => key.startsWith(prefix))) {
103487
+ safeVars[key] = value;
103488
+ }
103489
+ }
103490
+ // Add current working directory
103491
+ safeVars['PWD'] = process.cwd();
103492
+ return safeVars;
103493
+ }
103494
+ getSupportedConfigKeys() {
103495
+ return ['type', 'exec', 'transform', 'env', 'depends_on', 'on', 'if', 'group', 'forEach'];
103496
+ }
103497
+ async isAvailable() {
103498
+ // Command provider is always available as long as we can execute commands
103499
+ return true;
103500
+ }
103501
+ getRequirements() {
103502
+ return [
103503
+ 'Valid shell command to execute',
103504
+ 'Shell environment available',
103505
+ 'Optional: Transform template for processing output',
103506
+ ];
103507
+ }
103508
+ }
103509
+ exports.CommandCheckProvider = CommandCheckProvider;
103510
+
103511
+
103259
103512
  /***/ }),
103260
103513
 
103261
103514
  /***/ 31115:
@@ -103422,7 +103675,6 @@ class HttpCheckProvider extends check_provider_interface_1.CheckProvider {
103422
103675
  : [];
103423
103676
  return {
103424
103677
  issues,
103425
- suggestions: Array.isArray(response.suggestions) ? response.suggestions : [],
103426
103678
  };
103427
103679
  }
103428
103680
  createErrorResult(url, error) {
@@ -103441,7 +103693,6 @@ class HttpCheckProvider extends check_provider_interface_1.CheckProvider {
103441
103693
  replacement: undefined,
103442
103694
  },
103443
103695
  ],
103444
- suggestions: [`Webhook ${url} failed: ${errorMessage}`],
103445
103696
  };
103446
103697
  }
103447
103698
  validateSeverity(severity) {
@@ -103602,16 +103853,14 @@ class HttpClientProvider extends check_provider_interface_1.CheckProvider {
103602
103853
  category: 'logic',
103603
103854
  },
103604
103855
  ],
103605
- suggestions: [],
103606
103856
  };
103607
103857
  }
103608
103858
  }
103609
- // Return the fetched data as suggestions for dependent checks to access
103859
+ // Return the fetched data as a custom field for dependent checks to access
103610
103860
  return {
103611
103861
  issues: [],
103612
- suggestions: [
103613
- typeof processedData === 'string' ? processedData : JSON.stringify(processedData),
103614
- ],
103862
+ // Add custom data field that will be passed through to dependent checks
103863
+ data: processedData,
103615
103864
  };
103616
103865
  }
103617
103866
  catch (error) {
@@ -103626,7 +103875,6 @@ class HttpClientProvider extends check_provider_interface_1.CheckProvider {
103626
103875
  category: 'logic',
103627
103876
  },
103628
103877
  ],
103629
- suggestions: [],
103630
103878
  };
103631
103879
  }
103632
103880
  }
@@ -103781,7 +104029,6 @@ class HttpInputProvider extends check_provider_interface_1.CheckProvider {
103781
104029
  if (!webhookData) {
103782
104030
  return {
103783
104031
  issues: [],
103784
- suggestions: [`Waiting for webhook data on endpoint: ${endpoint}`],
103785
104032
  };
103786
104033
  }
103787
104034
  // Apply transformation if specified
@@ -103813,15 +104060,15 @@ class HttpInputProvider extends check_provider_interface_1.CheckProvider {
103813
104060
  category: 'logic',
103814
104061
  },
103815
104062
  ],
103816
- suggestions: [],
103817
104063
  };
103818
104064
  }
103819
104065
  }
103820
- // Return the processed data as suggestions for dependent checks to access
103821
- // We encode the data as JSON in a suggestion so it can be accessed via outputs
104066
+ // Return the processed data as a custom field for dependent checks to access
104067
+ // This will be available in outputs for dependent checks
103822
104068
  return {
103823
104069
  issues: [],
103824
- suggestions: [JSON.stringify(processedData)],
104070
+ // Add custom data field that will be passed through
104071
+ data: processedData,
103825
104072
  };
103826
104073
  }
103827
104074
  getWebhookData(endpoint) {
@@ -103917,9 +104164,14 @@ class LogCheckProvider extends check_provider_interface_1.CheckProvider {
103917
104164
  const renderedMessage = await this.liquid.parseAndRender(message, templateContext);
103918
104165
  // Build the log output
103919
104166
  const logOutput = this.formatLogOutput(level, renderedMessage, templateContext, includePrContext, includeDependencies, includeMetadata);
104167
+ // Output to console based on log level
104168
+ const logFn = level === 'error' ? console.error : level === 'warn' ? console.warn : console.log;
104169
+ logFn(logOutput);
104170
+ // Return with the log content as custom data for dependent checks
103920
104171
  return {
103921
- issues: [], // Log provider doesn't generate issues
103922
- suggestions: [logOutput], // Put formatted log output as the primary suggestion
104172
+ issues: [],
104173
+ // Add log output as custom field
104174
+ logOutput,
103923
104175
  };
103924
104176
  }
103925
104177
  buildTemplateContext(prInfo, dependencyResults, includePrContext = true, includeDependencies = true, includeMetadata = true) {
@@ -103952,9 +104204,8 @@ class LogCheckProvider extends check_provider_interface_1.CheckProvider {
103952
104204
  for (const [checkName, result] of dependencyResults.entries()) {
103953
104205
  dependencies[checkName] = {
103954
104206
  issueCount: result.issues?.length || 0,
103955
- suggestionCount: result.suggestions?.length || 0,
104207
+ suggestionCount: 0,
103956
104208
  issues: result.issues || [],
103957
- suggestions: result.suggestions || [],
103958
104209
  };
103959
104210
  }
103960
104211
  context.dependencies = dependencies;
@@ -104097,7 +104348,6 @@ class NoopCheckProvider extends check_provider_interface_1.CheckProvider {
104097
104348
  // It exists purely for command orchestration and dependency triggering
104098
104349
  return {
104099
104350
  issues: [],
104100
- suggestions: [],
104101
104351
  };
104102
104352
  }
104103
104353
  getSupportedConfigKeys() {
@@ -104117,193 +104367,6 @@ class NoopCheckProvider extends check_provider_interface_1.CheckProvider {
104117
104367
  exports.NoopCheckProvider = NoopCheckProvider;
104118
104368
 
104119
104369
 
104120
- /***/ }),
104121
-
104122
- /***/ 70477:
104123
- /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
104124
-
104125
- "use strict";
104126
-
104127
- Object.defineProperty(exports, "__esModule", ({ value: true }));
104128
- exports.ToolCheckProvider = void 0;
104129
- const check_provider_interface_1 = __nccwpck_require__(14131);
104130
- const issue_filter_1 = __nccwpck_require__(36879);
104131
- const child_process_1 = __nccwpck_require__(35317);
104132
- const liquidjs_1 = __nccwpck_require__(48694);
104133
- /**
104134
- * Check provider that executes external tools and commands with Liquid template support
104135
- * Supports both simple commands and complex templated execution with stdin
104136
- */
104137
- class ToolCheckProvider extends check_provider_interface_1.CheckProvider {
104138
- liquid;
104139
- constructor() {
104140
- super();
104141
- this.liquid = new liquidjs_1.Liquid({
104142
- strictVariables: false,
104143
- strictFilters: false,
104144
- });
104145
- }
104146
- getName() {
104147
- return 'tool';
104148
- }
104149
- getDescription() {
104150
- return 'Execute external code analysis tools (ESLint, Prettier, etc.)';
104151
- }
104152
- async validateConfig(config) {
104153
- if (!config || typeof config !== 'object') {
104154
- return false;
104155
- }
104156
- const cfg = config;
104157
- // Type must be 'tool'
104158
- if (cfg.type !== 'tool') {
104159
- return false;
104160
- }
104161
- // Must have exec specified for tool execution
104162
- if (typeof cfg.exec !== 'string' || !cfg.exec) {
104163
- return false;
104164
- }
104165
- return true;
104166
- }
104167
- async execute(prInfo, config, _dependencyResults, _sessionInfo) {
104168
- const execTemplate = config.exec;
104169
- const stdinTemplate = config.stdin;
104170
- // Prepare template context
104171
- const templateContext = {
104172
- pr: {
104173
- number: prInfo.number,
104174
- title: prInfo.title,
104175
- body: prInfo.body,
104176
- author: prInfo.author,
104177
- base: prInfo.base,
104178
- head: prInfo.head,
104179
- totalAdditions: prInfo.totalAdditions,
104180
- totalDeletions: prInfo.totalDeletions,
104181
- },
104182
- files: prInfo.files.map(f => ({
104183
- filename: f.filename,
104184
- status: f.status,
104185
- additions: f.additions,
104186
- deletions: f.deletions,
104187
- changes: f.changes,
104188
- patch: f.patch,
104189
- })),
104190
- // Add convenience arrays for common use cases
104191
- filenames: prInfo.files.map(f => f.filename),
104192
- config: config, // Allow access to config values in templates
104193
- };
104194
- // Render the command template
104195
- const renderedCommand = await this.liquid.parseAndRender(execTemplate, templateContext);
104196
- // Render stdin if provided
104197
- let renderedStdin;
104198
- if (stdinTemplate) {
104199
- renderedStdin = await this.liquid.parseAndRender(stdinTemplate, templateContext);
104200
- }
104201
- // Execute the tool
104202
- const output = await this.executeCommand(renderedCommand.trim(), renderedStdin);
104203
- // Parse tool output (this would be customized per tool)
104204
- const comments = this.parseToolOutput(output, renderedCommand);
104205
- const issues = comments.map(comment => ({
104206
- file: comment.file,
104207
- line: comment.line,
104208
- endLine: undefined,
104209
- ruleId: `tool/${comment.category}`,
104210
- message: comment.message,
104211
- severity: comment.severity,
104212
- category: comment.category,
104213
- suggestion: undefined,
104214
- replacement: undefined,
104215
- }));
104216
- // Apply issue suppression filtering
104217
- const suppressionEnabled = config.suppressionEnabled !== false;
104218
- const issueFilter = new issue_filter_1.IssueFilter(suppressionEnabled);
104219
- const filteredIssues = issueFilter.filterIssues(issues, process.cwd());
104220
- return {
104221
- issues: filteredIssues,
104222
- suggestions: this.generateSuggestions(comments, renderedCommand),
104223
- };
104224
- }
104225
- async executeCommand(command, stdin) {
104226
- return new Promise((resolve, reject) => {
104227
- // Parse command and arguments (handle quoted arguments)
104228
- const parts = command.match(/(?:[^\s"]+|"[^"]*")+/g) || [command];
104229
- const cmd = parts[0];
104230
- const args = parts.slice(1).map(arg => arg.replace(/^"(.*)"$/, '$1'));
104231
- const child = (0, child_process_1.spawn)(cmd, args, {
104232
- shell: false,
104233
- stdio: ['pipe', 'pipe', 'pipe'],
104234
- });
104235
- let output = '';
104236
- let error = '';
104237
- child.stdout.on('data', data => {
104238
- output += data.toString();
104239
- });
104240
- child.stderr.on('data', data => {
104241
- error += data.toString();
104242
- });
104243
- // Send stdin data if provided
104244
- if (stdin) {
104245
- child.stdin.write(stdin);
104246
- child.stdin.end();
104247
- }
104248
- child.on('close', _code => {
104249
- // Many tools return non-zero on issues found
104250
- resolve(output || error);
104251
- });
104252
- child.on('error', err => {
104253
- reject(new Error(`Failed to execute ${cmd}: ${err.message}`));
104254
- });
104255
- });
104256
- }
104257
- parseToolOutput(output, _command) {
104258
- const comments = [];
104259
- // This is a simplified parser - real implementation would handle specific tool formats
104260
- const lines = output.split('\n');
104261
- for (const line of lines) {
104262
- // Example: file.js:10:5: error: Missing semicolon
104263
- const match = line.match(/^(.+?):(\d+):(\d+):\s*(critical|error|warning|info):\s*(.+)$/);
104264
- if (match) {
104265
- const severity = match[4];
104266
- comments.push({
104267
- file: match[1],
104268
- line: parseInt(match[2]),
104269
- message: match[5],
104270
- severity: severity,
104271
- category: 'style',
104272
- });
104273
- }
104274
- }
104275
- return comments;
104276
- }
104277
- generateSuggestions(comments, command) {
104278
- const suggestions = [];
104279
- if (comments.length > 0) {
104280
- suggestions.push(`Fix ${comments.length} issues found by ${command}`);
104281
- const errorCount = comments.filter(c => c.severity === 'error').length;
104282
- if (errorCount > 0) {
104283
- suggestions.push(`Priority: Fix ${errorCount} errors before merging`);
104284
- }
104285
- }
104286
- return suggestions;
104287
- }
104288
- getSupportedConfigKeys() {
104289
- return ['type', 'exec', 'command', 'stdin', 'timeout', 'workingDirectory'];
104290
- }
104291
- async isAvailable() {
104292
- // Check if common tools are available
104293
- // In a real implementation, this would check for specific tools based on config
104294
- return true;
104295
- }
104296
- getRequirements() {
104297
- return [
104298
- 'External tool must be installed (e.g., eslint, prettier)',
104299
- 'Tool must be accessible in PATH',
104300
- 'Appropriate configuration files for the tool',
104301
- ];
104302
- }
104303
- }
104304
- exports.ToolCheckProvider = ToolCheckProvider;
104305
-
104306
-
104307
104370
  /***/ }),
104308
104371
 
104309
104372
  /***/ 532:
@@ -104355,7 +104418,7 @@ const ai_review_service_1 = __nccwpck_require__(51796);
104355
104418
  // Test utility function - Convert old ReviewSummary to new GroupedCheckResults format
104356
104419
  // This is for backward compatibility with tests only
104357
104420
  function convertReviewSummaryToGroupedResults(reviewSummary, checkName = 'test-check', groupName = 'default') {
104358
- // Create a simple content string from issues and suggestions
104421
+ // Create a simple content string from issues
104359
104422
  let content = '';
104360
104423
  if (reviewSummary.issues && reviewSummary.issues.length > 0) {
104361
104424
  content += `## Issues Found (${reviewSummary.issues.length})\n\n`;
@@ -104364,12 +104427,6 @@ function convertReviewSummaryToGroupedResults(reviewSummary, checkName = 'test-c
104364
104427
  });
104365
104428
  content += '\n';
104366
104429
  }
104367
- if (reviewSummary.suggestions && reviewSummary.suggestions.length > 0) {
104368
- content += `## Suggestions\n\n`;
104369
- reviewSummary.suggestions.forEach(suggestion => {
104370
- content += `- ${suggestion}\n`;
104371
- });
104372
- }
104373
104430
  if (!content) {
104374
104431
  content = 'No issues found.';
104375
104432
  }
@@ -126287,13 +126344,19 @@ For GitHub-compatible mermaid diagrams, avoid single quotes and parentheses in n
126287
126344
 
126288
126345
  **Rules:**
126289
126346
  - NO single quotes in any node labels: 'text' \u2192 "text" or text
126290
- - NO parentheses in square brackets: [Text (detail)] \u2192 [Text - detail]
126347
+ - NO parentheses in square brackets: [Text (detail)] \u2192 [Text - detail]
126291
126348
  - NO complex expressions in diamonds: {a && b} \u2192 {condition}
126349
+ - NO HTML tags in node labels: [<pre>code</pre>] \u2192 ["code block"] or [Code Block]
126292
126350
  - USE single quotes for styles and classes: classDef highlight fill:'#ff9999'
126351
+ - CRITICAL: When using quotes in node labels, place them INSIDE the brackets: ["quoted text"], NOT [quoted text"]
126293
126352
 
126294
126353
  **Examples:**
126295
126354
  - \u2705 [Load Config] ["Run command"] {Valid?}
126355
+ - \u2705 ["depends_on: [generate-items]"] (correct quote placement)
126356
+ - \u2705 ["Code Block"] (clean text instead of HTML)
126296
126357
  - \u274C [Load (config)] [Run 'command'] {isValid('x')}
126358
+ - \u274C [depends_on: [generate-items"] (incorrect quote placement - quote ends inside bracket)
126359
+ - \u274C [<pre>depends_on: [generate-items]</pre>] (HTML tags in node labels)
126297
126360
 
126298
126361
  **Diagram Type Selection:**
126299
126362
 
@@ -129221,7 +129284,7 @@ Examples:
129221
129284
  </extract>
129222
129285
 
129223
129286
  <attempt_completion>
129224
- <result>The configuration is loaded from src/config.js lines 15-25 which contains the database settings.</result>
129287
+ The configuration is loaded from src/config.js lines 15-25 which contains the database settings.
129225
129288
  </attempt_completion>
129226
129289
 
129227
129290
  # Special Case: Quick Completion
@@ -129248,7 +129311,7 @@ I need to find code related to error handling in the search module. The most app
129248
129311
  6. Wait for the tool execution result, which will be provided in the next message (within a <tool_result> block).
129249
129312
  7. Analyze the tool result and decide the next step. If more tool calls are needed, repeat steps 2-6.
129250
129313
  8. If the task is fully complete and all previous steps were successful, use the \`<attempt_completion>\` tool to provide the final answer. This is the ONLY way to finish the task.
129251
- 9. If you cannot proceed (e.g., missing information, invalid request), explain the issue clearly before using \`<attempt_completion>\` with an appropriate message in the \`<result>\` tag.
129314
+ 9. If you cannot proceed (e.g., missing information, invalid request), use \`<attempt_completion>\` to explain the issue clearly with an appropriate message directly inside the tags.
129252
129315
  10. If your previous response was already correct and complete, you may use \`<attempt_complete>\` as a shorthand.
129253
129316
 
129254
129317
  Available Tools: