@aiready/core 0.21.21 → 0.22.0

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.d.mts CHANGED
@@ -769,6 +769,7 @@ declare function calculateAiSignalClarity(params: {
769
769
  deepCallbacks: number;
770
770
  ambiguousNames: number;
771
771
  undocumentedExports: number;
772
+ largeFiles?: number;
772
773
  totalSymbols: number;
773
774
  totalExports: number;
774
775
  }): AiSignalClarity;
@@ -987,4 +988,28 @@ declare function getRepoMetadata(directory: string): {
987
988
  author?: string;
988
989
  };
989
990
 
990
- export { AIReadyConfig, type ASTNode, AcceptancePrediction, type AgentGroundingScore, type AiSignalClarity, type AiSignalClaritySignal, type CLIOptions, CSharpParser, type ChangeAmplificationScore, type CognitiveLoad, ComprehensionDifficulty, type ConceptCohesion, CostConfig, DEFAULT_COST_CONFIG, DEFAULT_EXCLUDE, type DependencyHealthScore, type DocDriftRisk, ExportInfo, type ExportWithImports, type FileImport, type FileWithDomain, GoParser, JavaParser, type KnowledgeConcentrationRisk, Language, LanguageParser, type LoadFactor, MODEL_PRICING_PRESETS, ModelContextTier, type ModelPricingPreset, NamingConvention, ParseResult, ParserFactory, type PatternEntropy, ProductivityImpact, PythonParser, SEVERITY_TIME_ESTIMATES, ScanOptions, type ScoreHistoryEntry, type ScoreTrend, type SemanticDistance, SpokeOutput, type TechnicalDebtInterest, TechnicalValueChain, TechnicalValueChainSummary, type TestabilityIndex, TokenBudget, ToolName, type ToolProvider, ToolRegistry, ToolScoringOutput, TypeScriptParser, VAGUE_FILE_NAMES, calculateAgentGrounding, calculateAiSignalClarity, calculateBusinessROI, calculateChangeAmplification, calculateCognitiveLoad, calculateComprehensionDifficulty, calculateConceptCohesion, calculateDebtInterest, calculateDependencyHealth, calculateDocDrift, calculateExtendedFutureProofScore, calculateFutureProofScore, calculateImportSimilarity, calculateKnowledgeConcentration, calculateMonthlyCost, calculatePatternEntropy, calculateProductivityImpact, calculateSemanticDistance, calculateTechnicalValueChain, calculateTestabilityIndex, calculateTokenBudget, clearHistory, emitProgress, estimateCostFromBudget, estimateTokens, exportHistory, extractFunctions, extractImports, formatAcceptanceRate, formatCost, formatHours, generateValueChain, getElapsedTime, getFileCommitTimestamps, getFileExtension, getHistorySummary, getLineRangeLastModifiedCached, getModelPreset, getParser, getRepoMetadata, getSafetyIcon, getScoreBar, getSeverityColor, getSupportedLanguages, getWasmPath, handleCLIError, handleJSONOutput, initTreeSitter, initializeParsers, isFileSupported, isSourceFile, loadConfig, loadMergedConfig, loadScoreHistory, mergeConfigWithDefaults, parseCode, parseFileExports, predictAcceptanceRate, readFileContent, resolveOutputPath, saveScoreEntry, scanEntries, scanFiles, setupParser, validateSpokeOutput, validateWithSchema };
991
+ /**
992
+ * Utilities for GitHub Actions integration
993
+ */
994
+ /**
995
+ * Emit a GitHub Action annotation
996
+ * Format: ::(error|warning|notice) file={file},line={line},col={col},title={title}::{message}
997
+ */
998
+ declare function emitAnnotation(params: {
999
+ level: 'error' | 'warning' | 'notice';
1000
+ file: string;
1001
+ line?: number;
1002
+ col?: number;
1003
+ title?: string;
1004
+ message: string;
1005
+ }): void;
1006
+ /**
1007
+ * Map AIReady severity to GitHub Action annotation level
1008
+ */
1009
+ declare function severityToAnnotationLevel(severity: string): 'error' | 'warning' | 'notice';
1010
+ /**
1011
+ * Emit multiple annotations from an array of issues
1012
+ */
1013
+ declare function emitIssuesAsAnnotations(issues: any[]): void;
1014
+
1015
+ export { AIReadyConfig, type ASTNode, AcceptancePrediction, type AgentGroundingScore, type AiSignalClarity, type AiSignalClaritySignal, type CLIOptions, CSharpParser, type ChangeAmplificationScore, type CognitiveLoad, ComprehensionDifficulty, type ConceptCohesion, CostConfig, DEFAULT_COST_CONFIG, DEFAULT_EXCLUDE, type DependencyHealthScore, type DocDriftRisk, ExportInfo, type ExportWithImports, type FileImport, type FileWithDomain, GoParser, JavaParser, type KnowledgeConcentrationRisk, Language, LanguageParser, type LoadFactor, MODEL_PRICING_PRESETS, ModelContextTier, type ModelPricingPreset, NamingConvention, ParseResult, ParserFactory, type PatternEntropy, ProductivityImpact, PythonParser, SEVERITY_TIME_ESTIMATES, ScanOptions, type ScoreHistoryEntry, type ScoreTrend, type SemanticDistance, SpokeOutput, type TechnicalDebtInterest, TechnicalValueChain, TechnicalValueChainSummary, type TestabilityIndex, TokenBudget, ToolName, type ToolProvider, ToolRegistry, ToolScoringOutput, TypeScriptParser, VAGUE_FILE_NAMES, calculateAgentGrounding, calculateAiSignalClarity, calculateBusinessROI, calculateChangeAmplification, calculateCognitiveLoad, calculateComprehensionDifficulty, calculateConceptCohesion, calculateDebtInterest, calculateDependencyHealth, calculateDocDrift, calculateExtendedFutureProofScore, calculateFutureProofScore, calculateImportSimilarity, calculateKnowledgeConcentration, calculateMonthlyCost, calculatePatternEntropy, calculateProductivityImpact, calculateSemanticDistance, calculateTechnicalValueChain, calculateTestabilityIndex, calculateTokenBudget, clearHistory, emitAnnotation, emitIssuesAsAnnotations, emitProgress, estimateCostFromBudget, estimateTokens, exportHistory, extractFunctions, extractImports, formatAcceptanceRate, formatCost, formatHours, generateValueChain, getElapsedTime, getFileCommitTimestamps, getFileExtension, getHistorySummary, getLineRangeLastModifiedCached, getModelPreset, getParser, getRepoMetadata, getSafetyIcon, getScoreBar, getSeverityColor, getSupportedLanguages, getWasmPath, handleCLIError, handleJSONOutput, initTreeSitter, initializeParsers, isFileSupported, isSourceFile, loadConfig, loadMergedConfig, loadScoreHistory, mergeConfigWithDefaults, parseCode, parseFileExports, predictAcceptanceRate, readFileContent, resolveOutputPath, saveScoreEntry, scanEntries, scanFiles, setupParser, severityToAnnotationLevel, validateSpokeOutput, validateWithSchema };
package/dist/index.d.ts CHANGED
@@ -769,6 +769,7 @@ declare function calculateAiSignalClarity(params: {
769
769
  deepCallbacks: number;
770
770
  ambiguousNames: number;
771
771
  undocumentedExports: number;
772
+ largeFiles?: number;
772
773
  totalSymbols: number;
773
774
  totalExports: number;
774
775
  }): AiSignalClarity;
@@ -987,4 +988,28 @@ declare function getRepoMetadata(directory: string): {
987
988
  author?: string;
988
989
  };
989
990
 
990
- export { AIReadyConfig, type ASTNode, AcceptancePrediction, type AgentGroundingScore, type AiSignalClarity, type AiSignalClaritySignal, type CLIOptions, CSharpParser, type ChangeAmplificationScore, type CognitiveLoad, ComprehensionDifficulty, type ConceptCohesion, CostConfig, DEFAULT_COST_CONFIG, DEFAULT_EXCLUDE, type DependencyHealthScore, type DocDriftRisk, ExportInfo, type ExportWithImports, type FileImport, type FileWithDomain, GoParser, JavaParser, type KnowledgeConcentrationRisk, Language, LanguageParser, type LoadFactor, MODEL_PRICING_PRESETS, ModelContextTier, type ModelPricingPreset, NamingConvention, ParseResult, ParserFactory, type PatternEntropy, ProductivityImpact, PythonParser, SEVERITY_TIME_ESTIMATES, ScanOptions, type ScoreHistoryEntry, type ScoreTrend, type SemanticDistance, SpokeOutput, type TechnicalDebtInterest, TechnicalValueChain, TechnicalValueChainSummary, type TestabilityIndex, TokenBudget, ToolName, type ToolProvider, ToolRegistry, ToolScoringOutput, TypeScriptParser, VAGUE_FILE_NAMES, calculateAgentGrounding, calculateAiSignalClarity, calculateBusinessROI, calculateChangeAmplification, calculateCognitiveLoad, calculateComprehensionDifficulty, calculateConceptCohesion, calculateDebtInterest, calculateDependencyHealth, calculateDocDrift, calculateExtendedFutureProofScore, calculateFutureProofScore, calculateImportSimilarity, calculateKnowledgeConcentration, calculateMonthlyCost, calculatePatternEntropy, calculateProductivityImpact, calculateSemanticDistance, calculateTechnicalValueChain, calculateTestabilityIndex, calculateTokenBudget, clearHistory, emitProgress, estimateCostFromBudget, estimateTokens, exportHistory, extractFunctions, extractImports, formatAcceptanceRate, formatCost, formatHours, generateValueChain, getElapsedTime, getFileCommitTimestamps, getFileExtension, getHistorySummary, getLineRangeLastModifiedCached, getModelPreset, getParser, getRepoMetadata, getSafetyIcon, getScoreBar, getSeverityColor, getSupportedLanguages, getWasmPath, handleCLIError, handleJSONOutput, initTreeSitter, initializeParsers, isFileSupported, isSourceFile, loadConfig, loadMergedConfig, loadScoreHistory, mergeConfigWithDefaults, parseCode, parseFileExports, predictAcceptanceRate, readFileContent, resolveOutputPath, saveScoreEntry, scanEntries, scanFiles, setupParser, validateSpokeOutput, validateWithSchema };
991
+ /**
992
+ * Utilities for GitHub Actions integration
993
+ */
994
+ /**
995
+ * Emit a GitHub Action annotation
996
+ * Format: ::(error|warning|notice) file={file},line={line},col={col},title={title}::{message}
997
+ */
998
+ declare function emitAnnotation(params: {
999
+ level: 'error' | 'warning' | 'notice';
1000
+ file: string;
1001
+ line?: number;
1002
+ col?: number;
1003
+ title?: string;
1004
+ message: string;
1005
+ }): void;
1006
+ /**
1007
+ * Map AIReady severity to GitHub Action annotation level
1008
+ */
1009
+ declare function severityToAnnotationLevel(severity: string): 'error' | 'warning' | 'notice';
1010
+ /**
1011
+ * Emit multiple annotations from an array of issues
1012
+ */
1013
+ declare function emitIssuesAsAnnotations(issues: any[]): void;
1014
+
1015
+ export { AIReadyConfig, type ASTNode, AcceptancePrediction, type AgentGroundingScore, type AiSignalClarity, type AiSignalClaritySignal, type CLIOptions, CSharpParser, type ChangeAmplificationScore, type CognitiveLoad, ComprehensionDifficulty, type ConceptCohesion, CostConfig, DEFAULT_COST_CONFIG, DEFAULT_EXCLUDE, type DependencyHealthScore, type DocDriftRisk, ExportInfo, type ExportWithImports, type FileImport, type FileWithDomain, GoParser, JavaParser, type KnowledgeConcentrationRisk, Language, LanguageParser, type LoadFactor, MODEL_PRICING_PRESETS, ModelContextTier, type ModelPricingPreset, NamingConvention, ParseResult, ParserFactory, type PatternEntropy, ProductivityImpact, PythonParser, SEVERITY_TIME_ESTIMATES, ScanOptions, type ScoreHistoryEntry, type ScoreTrend, type SemanticDistance, SpokeOutput, type TechnicalDebtInterest, TechnicalValueChain, TechnicalValueChainSummary, type TestabilityIndex, TokenBudget, ToolName, type ToolProvider, ToolRegistry, ToolScoringOutput, TypeScriptParser, VAGUE_FILE_NAMES, calculateAgentGrounding, calculateAiSignalClarity, calculateBusinessROI, calculateChangeAmplification, calculateCognitiveLoad, calculateComprehensionDifficulty, calculateConceptCohesion, calculateDebtInterest, calculateDependencyHealth, calculateDocDrift, calculateExtendedFutureProofScore, calculateFutureProofScore, calculateImportSimilarity, calculateKnowledgeConcentration, calculateMonthlyCost, calculatePatternEntropy, calculateProductivityImpact, calculateSemanticDistance, calculateTechnicalValueChain, calculateTestabilityIndex, calculateTokenBudget, clearHistory, emitAnnotation, emitIssuesAsAnnotations, emitProgress, estimateCostFromBudget, estimateTokens, exportHistory, extractFunctions, extractImports, formatAcceptanceRate, formatCost, formatHours, generateValueChain, getElapsedTime, getFileCommitTimestamps, getFileExtension, getHistorySummary, getLineRangeLastModifiedCached, getModelPreset, getParser, getRepoMetadata, getSafetyIcon, getScoreBar, getSeverityColor, getSupportedLanguages, getWasmPath, handleCLIError, handleJSONOutput, initTreeSitter, initializeParsers, isFileSupported, isSourceFile, loadConfig, loadMergedConfig, loadScoreHistory, mergeConfigWithDefaults, parseCode, parseFileExports, predictAcceptanceRate, readFileContent, resolveOutputPath, saveScoreEntry, scanEntries, scanFiles, setupParser, severityToAnnotationLevel, validateSpokeOutput, validateWithSchema };
package/dist/index.js CHANGED
@@ -95,6 +95,8 @@ __export(index_exports, {
95
95
  calculateTestabilityIndex: () => calculateTestabilityIndex,
96
96
  calculateTokenBudget: () => calculateTokenBudget,
97
97
  clearHistory: () => clearHistory,
98
+ emitAnnotation: () => emitAnnotation,
99
+ emitIssuesAsAnnotations: () => emitIssuesAsAnnotations,
98
100
  emitProgress: () => emitProgress,
99
101
  estimateCostFromBudget: () => estimateCostFromBudget,
100
102
  estimateTokens: () => estimateTokens,
@@ -148,6 +150,7 @@ __export(index_exports, {
148
150
  scanEntries: () => scanEntries,
149
151
  scanFiles: () => scanFiles,
150
152
  setupParser: () => setupParser,
153
+ severityToAnnotationLevel: () => severityToAnnotationLevel,
151
154
  validateSpokeOutput: () => validateSpokeOutput,
152
155
  validateWithSchema: () => validateWithSchema
153
156
  });
@@ -4011,6 +4014,8 @@ function calculateAiSignalClarity(params) {
4011
4014
  deepCallbacks,
4012
4015
  ambiguousNames,
4013
4016
  undocumentedExports,
4017
+ largeFiles = 0,
4018
+ // Default to 0 to prevent NaN
4014
4019
  totalSymbols,
4015
4020
  totalExports
4016
4021
  } = params;
@@ -4027,28 +4032,35 @@ function calculateAiSignalClarity(params) {
4027
4032
  const overloadSignal = {
4028
4033
  name: "Symbol Overloading",
4029
4034
  count: overloadedSymbols,
4030
- riskContribution: Math.round(Math.min(1, overloadRatio) * 100 * 0.25),
4035
+ riskContribution: Math.round(Math.min(1, overloadRatio) * 100 * 0.2),
4031
4036
  description: `${overloadedSymbols} overloaded symbols \u2014 AI picks wrong signature`
4032
4037
  };
4038
+ const largeFileSignal = {
4039
+ name: "Large Files",
4040
+ count: largeFiles,
4041
+ riskContribution: Math.round(Math.min(5, largeFiles) * 5),
4042
+ // up to 25 points
4043
+ description: `${largeFiles} large files \u2014 pushing AI context limits`
4044
+ };
4033
4045
  const magicRatio = magicLiterals / Math.max(1, totalSymbols * 2);
4034
4046
  const magicSignal = {
4035
4047
  name: "Magic Literals",
4036
4048
  count: magicLiterals,
4037
- riskContribution: Math.round(Math.min(1, magicRatio) * 100 * 0.2),
4049
+ riskContribution: Math.round(Math.min(1, magicRatio) * 100 * 0.15),
4038
4050
  description: `${magicLiterals} unnamed constants \u2014 AI invents wrong values`
4039
4051
  };
4040
4052
  const trapRatio = booleanTraps / Math.max(1, totalSymbols);
4041
4053
  const trapSignal = {
4042
4054
  name: "Boolean Traps",
4043
4055
  count: booleanTraps,
4044
- riskContribution: Math.round(Math.min(1, trapRatio) * 100 * 0.2),
4056
+ riskContribution: Math.round(Math.min(1, trapRatio) * 100 * 0.15),
4045
4057
  description: `${booleanTraps} boolean trap parameters \u2014 AI inverts intent`
4046
4058
  };
4047
4059
  const sideEffectRatio = implicitSideEffects / Math.max(1, totalExports);
4048
4060
  const sideEffectSignal = {
4049
4061
  name: "Implicit Side Effects",
4050
4062
  count: implicitSideEffects,
4051
- riskContribution: Math.round(Math.min(1, sideEffectRatio) * 100 * 0.15),
4063
+ riskContribution: Math.round(Math.min(1, sideEffectRatio) * 100 * 0.1),
4052
4064
  description: `${implicitSideEffects} functions with implicit side effects \u2014 AI misses contracts`
4053
4065
  };
4054
4066
  const callbackRatio = deepCallbacks / Math.max(1, totalSymbols * 0.1);
@@ -4062,18 +4074,19 @@ function calculateAiSignalClarity(params) {
4062
4074
  const ambiguousSignal = {
4063
4075
  name: "Ambiguous Names",
4064
4076
  count: ambiguousNames,
4065
- riskContribution: Math.round(Math.min(1, ambiguousRatio) * 100 * 0.1),
4077
+ riskContribution: Math.round(Math.min(1, ambiguousRatio) * 100 * 0.05),
4066
4078
  description: `${ambiguousNames} non-descriptive identifiers \u2014 AI guesses wrong intent`
4067
4079
  };
4068
4080
  const undocRatio = undocumentedExports / Math.max(1, totalExports);
4069
4081
  const undocSignal = {
4070
4082
  name: "Undocumented Exports",
4071
4083
  count: undocumentedExports,
4072
- riskContribution: Math.round(Math.min(1, undocRatio) * 100 * 0.1),
4084
+ riskContribution: Math.round(Math.min(1, undocRatio) * 100 * 0.05),
4073
4085
  description: `${undocumentedExports} public functions without docs \u2014 AI fabricates behavior`
4074
4086
  };
4075
4087
  const signals = [
4076
4088
  overloadSignal,
4089
+ largeFileSignal,
4077
4090
  magicSignal,
4078
4091
  trapSignal,
4079
4092
  sideEffectSignal,
@@ -4096,6 +4109,10 @@ function calculateAiSignalClarity(params) {
4096
4109
  );
4097
4110
  const topRisk = topSignal.riskContribution > 0 ? topSignal.description : "No significant issues detected";
4098
4111
  const recommendations = [];
4112
+ if (largeFileSignal.riskContribution > 5)
4113
+ recommendations.push(
4114
+ `Split ${largeFiles} large files (> 500 lines) into smaller, single-responsibility modules`
4115
+ );
4099
4116
  if (overloadSignal.riskContribution > 5)
4100
4117
  recommendations.push(
4101
4118
  `Rename ${overloadedSymbols} overloaded symbols to unique, intent-revealing names`
@@ -4731,6 +4748,46 @@ function getRepoMetadata(directory) {
4731
4748
  }
4732
4749
  return metadata;
4733
4750
  }
4751
+
4752
+ // src/utils/github-utils.ts
4753
+ function emitAnnotation(params) {
4754
+ const { level, file, line, col, title, message } = params;
4755
+ const parts = [];
4756
+ if (file) parts.push(`file=${file}`);
4757
+ if (line) parts.push(`line=${line}`);
4758
+ if (col) parts.push(`col=${col}`);
4759
+ if (title) parts.push(`title=${title}`);
4760
+ const metadata = parts.length > 0 ? ` ${parts.join(",")}` : "";
4761
+ console.log(`::${level}${metadata}::${message.replace(/\n/g, "%0A")}`);
4762
+ }
4763
+ function severityToAnnotationLevel(severity) {
4764
+ switch (severity.toLowerCase()) {
4765
+ case "critical":
4766
+ case "high-risk":
4767
+ case "blind-risk":
4768
+ return "error";
4769
+ case "major":
4770
+ case "moderate-risk":
4771
+ return "warning";
4772
+ case "minor":
4773
+ case "info":
4774
+ case "safe":
4775
+ default:
4776
+ return "notice";
4777
+ }
4778
+ }
4779
+ function emitIssuesAsAnnotations(issues) {
4780
+ issues.forEach((issue) => {
4781
+ emitAnnotation({
4782
+ level: severityToAnnotationLevel(issue.severity || "info"),
4783
+ file: issue.file || issue.fileName || "",
4784
+ line: issue.line || issue.location?.start?.line,
4785
+ col: issue.column || issue.location?.start?.column,
4786
+ title: `${issue.tool || "AIReady"}: ${issue.type || "Issue"}`,
4787
+ message: issue.message || issue.description || "No description provided"
4788
+ });
4789
+ });
4790
+ }
4734
4791
  // Annotate the CommonJS export names for ESM import in node:
4735
4792
  0 && (module.exports = {
4736
4793
  AnalysisResultSchema,
@@ -4798,6 +4855,8 @@ function getRepoMetadata(directory) {
4798
4855
  calculateTestabilityIndex,
4799
4856
  calculateTokenBudget,
4800
4857
  clearHistory,
4858
+ emitAnnotation,
4859
+ emitIssuesAsAnnotations,
4801
4860
  emitProgress,
4802
4861
  estimateCostFromBudget,
4803
4862
  estimateTokens,
@@ -4851,6 +4910,7 @@ function getRepoMetadata(directory) {
4851
4910
  scanEntries,
4852
4911
  scanFiles,
4853
4912
  setupParser,
4913
+ severityToAnnotationLevel,
4854
4914
  validateSpokeOutput,
4855
4915
  validateWithSchema
4856
4916
  });
package/dist/index.mjs CHANGED
@@ -3300,6 +3300,8 @@ function calculateAiSignalClarity(params) {
3300
3300
  deepCallbacks,
3301
3301
  ambiguousNames,
3302
3302
  undocumentedExports,
3303
+ largeFiles = 0,
3304
+ // Default to 0 to prevent NaN
3303
3305
  totalSymbols,
3304
3306
  totalExports
3305
3307
  } = params;
@@ -3316,28 +3318,35 @@ function calculateAiSignalClarity(params) {
3316
3318
  const overloadSignal = {
3317
3319
  name: "Symbol Overloading",
3318
3320
  count: overloadedSymbols,
3319
- riskContribution: Math.round(Math.min(1, overloadRatio) * 100 * 0.25),
3321
+ riskContribution: Math.round(Math.min(1, overloadRatio) * 100 * 0.2),
3320
3322
  description: `${overloadedSymbols} overloaded symbols \u2014 AI picks wrong signature`
3321
3323
  };
3324
+ const largeFileSignal = {
3325
+ name: "Large Files",
3326
+ count: largeFiles,
3327
+ riskContribution: Math.round(Math.min(5, largeFiles) * 5),
3328
+ // up to 25 points
3329
+ description: `${largeFiles} large files \u2014 pushing AI context limits`
3330
+ };
3322
3331
  const magicRatio = magicLiterals / Math.max(1, totalSymbols * 2);
3323
3332
  const magicSignal = {
3324
3333
  name: "Magic Literals",
3325
3334
  count: magicLiterals,
3326
- riskContribution: Math.round(Math.min(1, magicRatio) * 100 * 0.2),
3335
+ riskContribution: Math.round(Math.min(1, magicRatio) * 100 * 0.15),
3327
3336
  description: `${magicLiterals} unnamed constants \u2014 AI invents wrong values`
3328
3337
  };
3329
3338
  const trapRatio = booleanTraps / Math.max(1, totalSymbols);
3330
3339
  const trapSignal = {
3331
3340
  name: "Boolean Traps",
3332
3341
  count: booleanTraps,
3333
- riskContribution: Math.round(Math.min(1, trapRatio) * 100 * 0.2),
3342
+ riskContribution: Math.round(Math.min(1, trapRatio) * 100 * 0.15),
3334
3343
  description: `${booleanTraps} boolean trap parameters \u2014 AI inverts intent`
3335
3344
  };
3336
3345
  const sideEffectRatio = implicitSideEffects / Math.max(1, totalExports);
3337
3346
  const sideEffectSignal = {
3338
3347
  name: "Implicit Side Effects",
3339
3348
  count: implicitSideEffects,
3340
- riskContribution: Math.round(Math.min(1, sideEffectRatio) * 100 * 0.15),
3349
+ riskContribution: Math.round(Math.min(1, sideEffectRatio) * 100 * 0.1),
3341
3350
  description: `${implicitSideEffects} functions with implicit side effects \u2014 AI misses contracts`
3342
3351
  };
3343
3352
  const callbackRatio = deepCallbacks / Math.max(1, totalSymbols * 0.1);
@@ -3351,18 +3360,19 @@ function calculateAiSignalClarity(params) {
3351
3360
  const ambiguousSignal = {
3352
3361
  name: "Ambiguous Names",
3353
3362
  count: ambiguousNames,
3354
- riskContribution: Math.round(Math.min(1, ambiguousRatio) * 100 * 0.1),
3363
+ riskContribution: Math.round(Math.min(1, ambiguousRatio) * 100 * 0.05),
3355
3364
  description: `${ambiguousNames} non-descriptive identifiers \u2014 AI guesses wrong intent`
3356
3365
  };
3357
3366
  const undocRatio = undocumentedExports / Math.max(1, totalExports);
3358
3367
  const undocSignal = {
3359
3368
  name: "Undocumented Exports",
3360
3369
  count: undocumentedExports,
3361
- riskContribution: Math.round(Math.min(1, undocRatio) * 100 * 0.1),
3370
+ riskContribution: Math.round(Math.min(1, undocRatio) * 100 * 0.05),
3362
3371
  description: `${undocumentedExports} public functions without docs \u2014 AI fabricates behavior`
3363
3372
  };
3364
3373
  const signals = [
3365
3374
  overloadSignal,
3375
+ largeFileSignal,
3366
3376
  magicSignal,
3367
3377
  trapSignal,
3368
3378
  sideEffectSignal,
@@ -3385,6 +3395,10 @@ function calculateAiSignalClarity(params) {
3385
3395
  );
3386
3396
  const topRisk = topSignal.riskContribution > 0 ? topSignal.description : "No significant issues detected";
3387
3397
  const recommendations = [];
3398
+ if (largeFileSignal.riskContribution > 5)
3399
+ recommendations.push(
3400
+ `Split ${largeFiles} large files (> 500 lines) into smaller, single-responsibility modules`
3401
+ );
3388
3402
  if (overloadSignal.riskContribution > 5)
3389
3403
  recommendations.push(
3390
3404
  `Rename ${overloadedSymbols} overloaded symbols to unique, intent-revealing names`
@@ -4020,6 +4034,46 @@ function getRepoMetadata(directory) {
4020
4034
  }
4021
4035
  return metadata;
4022
4036
  }
4037
+
4038
+ // src/utils/github-utils.ts
4039
+ function emitAnnotation(params) {
4040
+ const { level, file, line, col, title, message } = params;
4041
+ const parts = [];
4042
+ if (file) parts.push(`file=${file}`);
4043
+ if (line) parts.push(`line=${line}`);
4044
+ if (col) parts.push(`col=${col}`);
4045
+ if (title) parts.push(`title=${title}`);
4046
+ const metadata = parts.length > 0 ? ` ${parts.join(",")}` : "";
4047
+ console.log(`::${level}${metadata}::${message.replace(/\n/g, "%0A")}`);
4048
+ }
4049
+ function severityToAnnotationLevel(severity) {
4050
+ switch (severity.toLowerCase()) {
4051
+ case "critical":
4052
+ case "high-risk":
4053
+ case "blind-risk":
4054
+ return "error";
4055
+ case "major":
4056
+ case "moderate-risk":
4057
+ return "warning";
4058
+ case "minor":
4059
+ case "info":
4060
+ case "safe":
4061
+ default:
4062
+ return "notice";
4063
+ }
4064
+ }
4065
+ function emitIssuesAsAnnotations(issues) {
4066
+ issues.forEach((issue) => {
4067
+ emitAnnotation({
4068
+ level: severityToAnnotationLevel(issue.severity || "info"),
4069
+ file: issue.file || issue.fileName || "",
4070
+ line: issue.line || issue.location?.start?.line,
4071
+ col: issue.column || issue.location?.start?.column,
4072
+ title: `${issue.tool || "AIReady"}: ${issue.type || "Issue"}`,
4073
+ message: issue.message || issue.description || "No description provided"
4074
+ });
4075
+ });
4076
+ }
4023
4077
  export {
4024
4078
  AnalysisResultSchema,
4025
4079
  AnalysisStatus,
@@ -4086,6 +4140,8 @@ export {
4086
4140
  calculateTestabilityIndex,
4087
4141
  calculateTokenBudget,
4088
4142
  clearHistory,
4143
+ emitAnnotation,
4144
+ emitIssuesAsAnnotations,
4089
4145
  emitProgress,
4090
4146
  estimateCostFromBudget,
4091
4147
  estimateTokens,
@@ -4139,6 +4195,7 @@ export {
4139
4195
  scanEntries,
4140
4196
  scanFiles,
4141
4197
  setupParser,
4198
+ severityToAnnotationLevel,
4142
4199
  validateSpokeOutput,
4143
4200
  validateWithSchema
4144
4201
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiready/core",
3
- "version": "0.21.21",
3
+ "version": "0.22.0",
4
4
  "description": "Shared utilities for AIReady analysis tools",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",