@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 +26 -1
- package/dist/index.d.ts +26 -1
- package/dist/index.js +66 -6
- package/dist/index.mjs +63 -6
- package/package.json +1 -1
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
|
-
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
};
|