@aiready/core 0.23.23 → 0.23.24
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/chunk-G4Z45SMK.mjs +852 -0
- package/dist/chunk-SM6INS52.mjs +501 -0
- package/dist/client/index.d.mts +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.js +4 -4
- package/dist/client/index.mjs +1 -1
- package/dist/index-CkM98qn1.d.mts +1299 -0
- package/dist/index-CkM98qn1.d.ts +1299 -0
- package/dist/index-DLHCsiAk.d.mts +1294 -0
- package/dist/index-DLHCsiAk.d.ts +1294 -0
- package/dist/index.d.mts +177 -139
- package/dist/index.d.ts +177 -139
- package/dist/index.js +467 -245
- package/dist/index.mjs +451 -240
- package/dist/python-parser-SJ3LFZFJ.mjs +8 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -965,8 +965,8 @@ var init_python_parser = __esm({
|
|
|
965
965
|
const fromMatch = line.match(fromImportRegex);
|
|
966
966
|
if (fromMatch) {
|
|
967
967
|
const module2 = fromMatch[1];
|
|
968
|
-
const
|
|
969
|
-
if (
|
|
968
|
+
const importsStr = fromMatch[2];
|
|
969
|
+
if (importsStr.trim() === "*") {
|
|
970
970
|
imports.push({
|
|
971
971
|
source: module2,
|
|
972
972
|
specifiers: ["*"],
|
|
@@ -977,7 +977,7 @@ var init_python_parser = __esm({
|
|
|
977
977
|
});
|
|
978
978
|
return;
|
|
979
979
|
}
|
|
980
|
-
const specifiers =
|
|
980
|
+
const specifiers = importsStr.split(",").map((s) => s.trim().split(" as ")[0]);
|
|
981
981
|
imports.push({
|
|
982
982
|
source: module2,
|
|
983
983
|
specifiers,
|
|
@@ -1994,6 +1994,7 @@ __export(index_exports, {
|
|
|
1994
1994
|
SeveritySchema: () => SeveritySchema,
|
|
1995
1995
|
SpokeOutputSchema: () => SpokeOutputSchema,
|
|
1996
1996
|
SpokeSummarySchema: () => SpokeSummarySchema,
|
|
1997
|
+
TEST_PATTERNS: () => TEST_PATTERNS,
|
|
1997
1998
|
TOOL_NAME_MAP: () => TOOL_NAME_MAP,
|
|
1998
1999
|
ToolName: () => ToolName,
|
|
1999
2000
|
ToolNameSchema: () => ToolNameSchema,
|
|
@@ -2033,14 +2034,18 @@ __export(index_exports, {
|
|
|
2033
2034
|
clearHistory: () => clearHistory,
|
|
2034
2035
|
createProvider: () => createProvider,
|
|
2035
2036
|
createStandardProgressCallback: () => createStandardProgressCallback,
|
|
2037
|
+
detectTestFramework: () => detectTestFramework,
|
|
2036
2038
|
displayStandardConsoleReport: () => displayStandardConsoleReport,
|
|
2037
2039
|
emitAnnotation: () => emitAnnotation,
|
|
2038
2040
|
emitIssuesAsAnnotations: () => emitIssuesAsAnnotations,
|
|
2039
2041
|
emitProgress: () => emitProgress,
|
|
2042
|
+
ensureDir: () => ensureDir,
|
|
2040
2043
|
estimateCostFromBudget: () => estimateCostFromBudget,
|
|
2041
2044
|
estimateTokens: () => estimateTokens,
|
|
2045
|
+
executeSpokeCli: () => executeSpokeCli,
|
|
2042
2046
|
exportHistory: () => exportHistory,
|
|
2043
2047
|
extractCodeBlocks: () => extractCodeBlocks,
|
|
2048
|
+
filterBySeverity: () => filterBySeverity,
|
|
2044
2049
|
findLatestReport: () => findLatestReport,
|
|
2045
2050
|
findLatestScanReport: () => findLatestScanReport,
|
|
2046
2051
|
formatAcceptanceRate: () => formatAcceptanceRate,
|
|
@@ -2056,13 +2061,14 @@ __export(index_exports, {
|
|
|
2056
2061
|
generateReportFooter: () => generateReportFooter,
|
|
2057
2062
|
generateReportHead: () => generateReportHead,
|
|
2058
2063
|
generateReportHero: () => generateReportHero,
|
|
2059
|
-
|
|
2064
|
+
generateStandardHtmlReport: () => generateStandardHtmlReport,
|
|
2060
2065
|
generateStatCards: () => generateStatCards,
|
|
2061
2066
|
generateTable: () => generateTable,
|
|
2062
2067
|
generateValueChain: () => generateValueChain,
|
|
2063
2068
|
getElapsedTime: () => getElapsedTime,
|
|
2064
2069
|
getFileCommitTimestamps: () => getFileCommitTimestamps,
|
|
2065
2070
|
getFileExtension: () => getFileExtension,
|
|
2071
|
+
getFilesByPattern: () => getFilesByPattern,
|
|
2066
2072
|
getHistorySummary: () => getHistorySummary,
|
|
2067
2073
|
getLineRangeLastModifiedCached: () => getLineRangeLastModifiedCached,
|
|
2068
2074
|
getModelPreset: () => getModelPreset,
|
|
@@ -2085,6 +2091,7 @@ __export(index_exports, {
|
|
|
2085
2091
|
getSeverityBadge: () => getSeverityBadge,
|
|
2086
2092
|
getSeverityColor: () => getSeverityColor,
|
|
2087
2093
|
getSeverityEnum: () => getSeverityEnum,
|
|
2094
|
+
getSeverityLabel: () => getSeverityLabel,
|
|
2088
2095
|
getSeverityLevel: () => getSeverityLevel,
|
|
2089
2096
|
getSeverityValue: () => getSeverityValue,
|
|
2090
2097
|
getSupportedLanguages: () => getSupportedLanguages,
|
|
@@ -2099,8 +2106,10 @@ __export(index_exports, {
|
|
|
2099
2106
|
inferPatternType: () => inferPatternType,
|
|
2100
2107
|
initTreeSitter: () => initTreeSitter,
|
|
2101
2108
|
initializeParsers: () => initializeParsers,
|
|
2109
|
+
isBuildArtifact: () => isBuildArtifact,
|
|
2102
2110
|
isFileSupported: () => isFileSupported,
|
|
2103
2111
|
isSourceFile: () => isSourceFile,
|
|
2112
|
+
isTestFile: () => isTestFile,
|
|
2104
2113
|
loadConfig: () => loadConfig,
|
|
2105
2114
|
loadMergedConfig: () => loadMergedConfig,
|
|
2106
2115
|
loadScoreHistory: () => loadScoreHistory,
|
|
@@ -2108,6 +2117,7 @@ __export(index_exports, {
|
|
|
2108
2117
|
normalizeAnalysisResult: () => normalizeAnalysisResult,
|
|
2109
2118
|
normalizeIssue: () => normalizeIssue,
|
|
2110
2119
|
normalizeMetrics: () => normalizeMetrics,
|
|
2120
|
+
normalizeSeverity: () => normalizeSeverity,
|
|
2111
2121
|
normalizeSpokeOutput: () => normalizeSpokeOutput,
|
|
2112
2122
|
normalizeToolName: () => normalizeToolName,
|
|
2113
2123
|
parseFileExports: () => parseFileExports,
|
|
@@ -2118,6 +2128,7 @@ __export(index_exports, {
|
|
|
2118
2128
|
readFileContent: () => readFileContent,
|
|
2119
2129
|
resolveOutputFormat: () => resolveOutputFormat,
|
|
2120
2130
|
resolveOutputPath: () => resolveOutputPath,
|
|
2131
|
+
runBatchAnalysis: () => runBatchAnalysis,
|
|
2121
2132
|
runStandardCliAction: () => runStandardCliAction,
|
|
2122
2133
|
saveScoreEntry: () => saveScoreEntry,
|
|
2123
2134
|
scanEntries: () => scanEntries,
|
|
@@ -2364,12 +2375,12 @@ var UnifiedReportSchema = import_zod6.z.object({
|
|
|
2364
2375
|
// src/types/schemas/config.ts
|
|
2365
2376
|
var import_zod7 = require("zod");
|
|
2366
2377
|
var AIReadyConfigSchema = import_zod7.z.object({
|
|
2367
|
-
/** Target score threshold (0-100) */
|
|
2368
|
-
threshold: import_zod7.z.number().optional(),
|
|
2369
|
-
/** Files or directories to include in scan */
|
|
2370
|
-
include: import_zod7.z.array(import_zod7.z.string()).optional(),
|
|
2371
2378
|
/** Files or directories to exclude from scan */
|
|
2372
2379
|
exclude: import_zod7.z.array(import_zod7.z.string()).optional(),
|
|
2380
|
+
/** Fail CI/CD if score below threshold (0-100) */
|
|
2381
|
+
threshold: import_zod7.z.number().optional(),
|
|
2382
|
+
/** Fail on issues: critical, major, any */
|
|
2383
|
+
failOn: import_zod7.z.enum(["critical", "major", "any", "none"]).optional(),
|
|
2373
2384
|
/** Scan-specific configuration */
|
|
2374
2385
|
scan: import_zod7.z.object({
|
|
2375
2386
|
include: import_zod7.z.array(import_zod7.z.string()).optional(),
|
|
@@ -2750,14 +2761,14 @@ async function scanFiles(options) {
|
|
|
2750
2761
|
ignoreFromFile = [];
|
|
2751
2762
|
}
|
|
2752
2763
|
}
|
|
2753
|
-
const
|
|
2764
|
+
const TEST_PATTERNS2 = [
|
|
2754
2765
|
"**/*.test.*",
|
|
2755
2766
|
"**/*.spec.*",
|
|
2756
2767
|
"**/__tests__/**",
|
|
2757
2768
|
"**/test/**",
|
|
2758
2769
|
"**/tests/**"
|
|
2759
2770
|
];
|
|
2760
|
-
const baseExclude = options.includeTests ? DEFAULT_EXCLUDE.filter((p) => !
|
|
2771
|
+
const baseExclude = options.includeTests ? DEFAULT_EXCLUDE.filter((p) => !TEST_PATTERNS2.includes(p)) : DEFAULT_EXCLUDE;
|
|
2761
2772
|
const finalExclude = [
|
|
2762
2773
|
.../* @__PURE__ */ new Set([...exclude || [], ...ignoreFromFile, ...baseExclude])
|
|
2763
2774
|
];
|
|
@@ -2819,14 +2830,14 @@ async function scanEntries(options) {
|
|
|
2819
2830
|
ignoreFromFile = [];
|
|
2820
2831
|
}
|
|
2821
2832
|
}
|
|
2822
|
-
const
|
|
2833
|
+
const TEST_PATTERNS2 = [
|
|
2823
2834
|
"**/*.test.*",
|
|
2824
2835
|
"**/*.spec.*",
|
|
2825
2836
|
"**/__tests__/**",
|
|
2826
2837
|
"**/test/**",
|
|
2827
2838
|
"**/tests/**"
|
|
2828
2839
|
];
|
|
2829
|
-
const baseExclude = includeTests ? DEFAULT_EXCLUDE.filter((p) => !
|
|
2840
|
+
const baseExclude = includeTests ? DEFAULT_EXCLUDE.filter((p) => !TEST_PATTERNS2.includes(p)) : DEFAULT_EXCLUDE;
|
|
2830
2841
|
const finalExclude = [
|
|
2831
2842
|
.../* @__PURE__ */ new Set([...exclude || [], ...ignoreFromFile, ...baseExclude])
|
|
2832
2843
|
];
|
|
@@ -2881,26 +2892,15 @@ function isSourceFile(filePath) {
|
|
|
2881
2892
|
return ["ts", "tsx", "js", "jsx", "py", "java", "go", "rs"].includes(ext);
|
|
2882
2893
|
}
|
|
2883
2894
|
|
|
2884
|
-
// src/utils/
|
|
2895
|
+
// src/utils/fs-utils.ts
|
|
2885
2896
|
var import_fs2 = require("fs");
|
|
2886
2897
|
var import_path2 = require("path");
|
|
2887
|
-
var import_chalk = __toESM(require("chalk"));
|
|
2888
2898
|
function ensureDir(path2) {
|
|
2889
2899
|
const dir = (0, import_path2.dirname)(path2);
|
|
2890
2900
|
if (!(0, import_fs2.existsSync)(dir)) {
|
|
2891
2901
|
(0, import_fs2.mkdirSync)(dir, { recursive: true });
|
|
2892
2902
|
}
|
|
2893
2903
|
}
|
|
2894
|
-
function normalizeSeverity(s) {
|
|
2895
|
-
if (!s) return null;
|
|
2896
|
-
const lower = s.toLowerCase();
|
|
2897
|
-
if (["critical", "high-risk", "blind-risk"].includes(lower))
|
|
2898
|
-
return "critical" /* Critical */;
|
|
2899
|
-
if (["major", "moderate-risk"].includes(lower)) return "major" /* Major */;
|
|
2900
|
-
if (["minor", "safe"].includes(lower)) return "minor" /* Minor */;
|
|
2901
|
-
if (lower === "info") return "info" /* Info */;
|
|
2902
|
-
return null;
|
|
2903
|
-
}
|
|
2904
2904
|
function getFilesByPattern(dir, pattern) {
|
|
2905
2905
|
if (!(0, import_fs2.existsSync)(dir)) return [];
|
|
2906
2906
|
try {
|
|
@@ -2927,16 +2927,6 @@ function resolveOutputPath(userPath, defaultFilename, workingDir = process.cwd()
|
|
|
2927
2927
|
ensureDir(outputPath);
|
|
2928
2928
|
return outputPath;
|
|
2929
2929
|
}
|
|
2930
|
-
async function loadMergedConfig(directory, defaults, cliOptions) {
|
|
2931
|
-
const config = await loadConfig(directory);
|
|
2932
|
-
const mergedConfig = mergeConfigWithDefaults(config, defaults);
|
|
2933
|
-
const result = {
|
|
2934
|
-
...mergedConfig,
|
|
2935
|
-
...cliOptions,
|
|
2936
|
-
rootDir: directory
|
|
2937
|
-
};
|
|
2938
|
-
return result;
|
|
2939
|
-
}
|
|
2940
2930
|
function handleJSONOutput(data, outputFile, successMessage) {
|
|
2941
2931
|
if (outputFile) {
|
|
2942
2932
|
ensureDir(outputFile);
|
|
@@ -2946,63 +2936,54 @@ function handleJSONOutput(data, outputFile, successMessage) {
|
|
|
2946
2936
|
console.log(JSON.stringify(data, null, 2));
|
|
2947
2937
|
}
|
|
2948
2938
|
}
|
|
2949
|
-
function
|
|
2950
|
-
const
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
function printTerminalHeader(title, color = import_chalk.default.cyan) {
|
|
2955
|
-
const divider = getTerminalDivider(color);
|
|
2956
|
-
console.log(divider);
|
|
2957
|
-
console.log(import_chalk.default.bold.white(` ${title.toUpperCase()}`));
|
|
2958
|
-
console.log(divider + "\n");
|
|
2959
|
-
}
|
|
2960
|
-
function handleCLIError(error, commandName) {
|
|
2961
|
-
console.error(`\u274C ${commandName} failed:`, error);
|
|
2962
|
-
process.exit(1);
|
|
2963
|
-
}
|
|
2964
|
-
function getElapsedTime(startTime) {
|
|
2965
|
-
return ((Date.now() - startTime) / 1e3).toFixed(2);
|
|
2966
|
-
}
|
|
2967
|
-
function getScoreBar(val) {
|
|
2968
|
-
const clamped = Math.max(0, Math.min(100, val));
|
|
2969
|
-
return "\u2588".repeat(Math.round(clamped / 10)).padEnd(10, "\u2591");
|
|
2970
|
-
}
|
|
2971
|
-
function getSafetyIcon(rating) {
|
|
2972
|
-
switch (rating) {
|
|
2973
|
-
case "safe":
|
|
2974
|
-
return "\u2705";
|
|
2975
|
-
case "moderate-risk":
|
|
2976
|
-
return "\u26A0\uFE0F ";
|
|
2977
|
-
case "high-risk":
|
|
2978
|
-
return "\u{1F534}";
|
|
2979
|
-
case "blind-risk":
|
|
2980
|
-
return "\u{1F480}";
|
|
2981
|
-
default:
|
|
2982
|
-
return "\u2753";
|
|
2939
|
+
function findLatestReport(dirPath) {
|
|
2940
|
+
const aireadyDir = (0, import_path2.resolve)(dirPath, ".aiready");
|
|
2941
|
+
let files = getFilesByPattern(aireadyDir, /^aiready-report-.*\.json$/);
|
|
2942
|
+
if (files.length === 0) {
|
|
2943
|
+
files = getFilesByPattern(aireadyDir, /^aiready-scan-.*\.json$/);
|
|
2983
2944
|
}
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
if (!onProgress) return;
|
|
2987
|
-
if (processed % throttleCount === 0 || processed === total) {
|
|
2988
|
-
onProgress(processed, total, `${message} (${processed}/${total})`);
|
|
2945
|
+
if (files.length === 0) {
|
|
2946
|
+
return null;
|
|
2989
2947
|
}
|
|
2948
|
+
const sortedFiles = files.map((f) => ({
|
|
2949
|
+
name: f,
|
|
2950
|
+
path: (0, import_path2.resolve)(aireadyDir, f),
|
|
2951
|
+
mtime: (0, import_fs2.statSync)((0, import_path2.resolve)(aireadyDir, f)).mtime
|
|
2952
|
+
})).sort((a, b) => b.mtime.getTime() - a.mtime.getTime());
|
|
2953
|
+
return sortedFiles[0].path;
|
|
2990
2954
|
}
|
|
2991
|
-
function
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
return
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
2955
|
+
function findLatestScanReport(scanReportsDir, reportFilePrefix) {
|
|
2956
|
+
try {
|
|
2957
|
+
const prefixRegex = new RegExp(`^${reportFilePrefix}\\d+\\.json$`);
|
|
2958
|
+
const reportFiles = getFilesByPattern(scanReportsDir, prefixRegex);
|
|
2959
|
+
if (reportFiles.length === 0) return null;
|
|
2960
|
+
reportFiles.sort((a, b) => {
|
|
2961
|
+
const idA = parseInt(a.match(/\d+/)?.[0] || "0", 10);
|
|
2962
|
+
const idB = parseInt(b.match(/\d+/)?.[0] || "0", 10);
|
|
2963
|
+
return idB - idA;
|
|
2964
|
+
});
|
|
2965
|
+
return (0, import_path2.join)(scanReportsDir, reportFiles[0]);
|
|
2966
|
+
} catch {
|
|
2967
|
+
console.error("Error while finding latest scan report");
|
|
2968
|
+
return null;
|
|
3004
2969
|
}
|
|
3005
2970
|
}
|
|
2971
|
+
|
|
2972
|
+
// src/utils/terminal-utils.ts
|
|
2973
|
+
var import_chalk2 = __toESM(require("chalk"));
|
|
2974
|
+
|
|
2975
|
+
// src/utils/severity-utils.ts
|
|
2976
|
+
var import_chalk = __toESM(require("chalk"));
|
|
2977
|
+
function normalizeSeverity(s) {
|
|
2978
|
+
if (!s) return null;
|
|
2979
|
+
const lower = s.toLowerCase();
|
|
2980
|
+
if (["critical", "high-risk", "blind-risk"].includes(lower))
|
|
2981
|
+
return "critical" /* Critical */;
|
|
2982
|
+
if (["major", "moderate-risk"].includes(lower)) return "major" /* Major */;
|
|
2983
|
+
if (["minor", "safe"].includes(lower)) return "minor" /* Minor */;
|
|
2984
|
+
if (lower === "info") return "info" /* Info */;
|
|
2985
|
+
return null;
|
|
2986
|
+
}
|
|
3006
2987
|
function getSeverityValue(s) {
|
|
3007
2988
|
const normalized = normalizeSeverity(s);
|
|
3008
2989
|
switch (normalized) {
|
|
@@ -3021,23 +3002,6 @@ function getSeverityValue(s) {
|
|
|
3021
3002
|
function getSeverityLevel(s) {
|
|
3022
3003
|
return getSeverityValue(s);
|
|
3023
3004
|
}
|
|
3024
|
-
function getSeverityBadge(severity, chalkInstance = import_chalk.default) {
|
|
3025
|
-
const val = getSeverityValue(
|
|
3026
|
-
typeof severity === "string" ? severity : severity
|
|
3027
|
-
);
|
|
3028
|
-
switch (val) {
|
|
3029
|
-
case 4:
|
|
3030
|
-
return chalkInstance.bgRed.white.bold(" CRITICAL ");
|
|
3031
|
-
case 3:
|
|
3032
|
-
return chalkInstance.bgYellow.black.bold(" MAJOR ");
|
|
3033
|
-
case 2:
|
|
3034
|
-
return chalkInstance.bgBlue.white.bold(" MINOR ");
|
|
3035
|
-
case 1:
|
|
3036
|
-
return chalkInstance.bgCyan.black(" INFO ");
|
|
3037
|
-
default:
|
|
3038
|
-
return chalkInstance.bgCyan.black(" INFO ");
|
|
3039
|
-
}
|
|
3040
|
-
}
|
|
3041
3005
|
function getSeverityEnum(s) {
|
|
3042
3006
|
const level = getSeverityLevel(s);
|
|
3043
3007
|
switch (level) {
|
|
@@ -3051,39 +3015,125 @@ function getSeverityEnum(s) {
|
|
|
3051
3015
|
return "info";
|
|
3052
3016
|
}
|
|
3053
3017
|
}
|
|
3054
|
-
function
|
|
3055
|
-
const
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3018
|
+
function getSeverityColor(severity, chalkInstance = import_chalk.default) {
|
|
3019
|
+
const normalized = normalizeSeverity(severity);
|
|
3020
|
+
switch (normalized) {
|
|
3021
|
+
case "critical" /* Critical */:
|
|
3022
|
+
return chalkInstance.red;
|
|
3023
|
+
case "major" /* Major */:
|
|
3024
|
+
return chalkInstance.yellow;
|
|
3025
|
+
case "minor" /* Minor */:
|
|
3026
|
+
return chalkInstance.green;
|
|
3027
|
+
case "info" /* Info */:
|
|
3028
|
+
return chalkInstance.blue;
|
|
3029
|
+
default:
|
|
3030
|
+
return chalkInstance.white;
|
|
3059
3031
|
}
|
|
3060
|
-
|
|
3061
|
-
|
|
3032
|
+
}
|
|
3033
|
+
function getSeverityBadge(severity, chalkInstance = import_chalk.default) {
|
|
3034
|
+
const normalized = normalizeSeverity(severity);
|
|
3035
|
+
switch (normalized) {
|
|
3036
|
+
case "critical" /* Critical */:
|
|
3037
|
+
return chalkInstance.bgRed.white.bold(" CRITICAL ");
|
|
3038
|
+
case "major" /* Major */:
|
|
3039
|
+
return chalkInstance.bgYellow.black.bold(" MAJOR ");
|
|
3040
|
+
case "minor" /* Minor */:
|
|
3041
|
+
return chalkInstance.bgGreen.black.bold(" MINOR ");
|
|
3042
|
+
case "info" /* Info */:
|
|
3043
|
+
return chalkInstance.bgBlue.white.bold(" INFO ");
|
|
3044
|
+
default:
|
|
3045
|
+
return chalkInstance.bgCyan.black(" UNKNOWN ");
|
|
3062
3046
|
}
|
|
3063
|
-
const sortedFiles = files.map((f) => ({
|
|
3064
|
-
name: f,
|
|
3065
|
-
path: (0, import_path2.resolve)(aireadyDir, f),
|
|
3066
|
-
mtime: (0, import_fs2.statSync)((0, import_path2.resolve)(aireadyDir, f)).mtime
|
|
3067
|
-
})).sort((a, b) => b.mtime.getTime() - a.mtime.getTime());
|
|
3068
|
-
return sortedFiles[0].path;
|
|
3069
3047
|
}
|
|
3070
|
-
function
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3048
|
+
function getSeverityLabel(severity) {
|
|
3049
|
+
const labels = {
|
|
3050
|
+
["critical" /* Critical */]: "\u{1F534} CRITICAL",
|
|
3051
|
+
["major" /* Major */]: "\u{1F7E1} MAJOR",
|
|
3052
|
+
["minor" /* Minor */]: "\u{1F535} MINOR",
|
|
3053
|
+
["info" /* Info */]: "\u2139\uFE0F INFO"
|
|
3054
|
+
};
|
|
3055
|
+
return labels[severity];
|
|
3056
|
+
}
|
|
3057
|
+
function filterBySeverity(items, minSeverity) {
|
|
3058
|
+
const severityOrder = [
|
|
3059
|
+
"info" /* Info */,
|
|
3060
|
+
"minor" /* Minor */,
|
|
3061
|
+
"major" /* Major */,
|
|
3062
|
+
"critical" /* Critical */
|
|
3063
|
+
];
|
|
3064
|
+
const minIndex = severityOrder.indexOf(minSeverity);
|
|
3065
|
+
if (minIndex === -1) return items;
|
|
3066
|
+
return items.filter((item) => {
|
|
3067
|
+
const itemIndex = severityOrder.indexOf(item.severity);
|
|
3068
|
+
return itemIndex >= minIndex;
|
|
3069
|
+
});
|
|
3070
|
+
}
|
|
3071
|
+
|
|
3072
|
+
// src/utils/terminal-utils.ts
|
|
3073
|
+
function getSafetyIcon(rating) {
|
|
3074
|
+
switch (rating) {
|
|
3075
|
+
case "safe":
|
|
3076
|
+
return "\u2705";
|
|
3077
|
+
case "moderate-risk":
|
|
3078
|
+
return "\u26A0\uFE0F ";
|
|
3079
|
+
case "high-risk":
|
|
3080
|
+
return "\u{1F534}";
|
|
3081
|
+
case "blind-risk":
|
|
3082
|
+
return "\u{1F480}";
|
|
3083
|
+
default:
|
|
3084
|
+
return "\u2753";
|
|
3085
|
+
}
|
|
3086
|
+
}
|
|
3087
|
+
|
|
3088
|
+
// src/utils/terminal-ui.ts
|
|
3089
|
+
var import_chalk3 = __toESM(require("chalk"));
|
|
3090
|
+
function printTerminalHeader(title, colorFn = import_chalk3.default.cyan.bold, width = 80) {
|
|
3091
|
+
const divider = "\u2501".repeat(width);
|
|
3092
|
+
console.log(colorFn(`
|
|
3093
|
+
${divider}`));
|
|
3094
|
+
console.log(colorFn(` ${title.toUpperCase()}`));
|
|
3095
|
+
console.log(colorFn(`${divider}
|
|
3096
|
+
`));
|
|
3097
|
+
}
|
|
3098
|
+
function getTerminalDivider(colorFn = import_chalk3.default.gray, width = 80) {
|
|
3099
|
+
return colorFn("\u2501".repeat(width));
|
|
3100
|
+
}
|
|
3101
|
+
function getScoreBar(score, width = 10) {
|
|
3102
|
+
const normalized = Math.max(0, Math.min(100, score));
|
|
3103
|
+
const solid = Math.round(normalized / 100 * width);
|
|
3104
|
+
const empty = width - solid;
|
|
3105
|
+
return "\u2588".repeat(solid) + "\u2591".repeat(empty);
|
|
3106
|
+
}
|
|
3107
|
+
|
|
3108
|
+
// src/utils/progress-utils.ts
|
|
3109
|
+
function emitProgress(processed, total, toolId, message, onProgress, throttleCount = 50) {
|
|
3110
|
+
if (!onProgress) return;
|
|
3111
|
+
if (processed % throttleCount === 0 || processed === total) {
|
|
3112
|
+
onProgress(processed, total, `${message} (${processed}/${total})`);
|
|
3084
3113
|
}
|
|
3085
3114
|
}
|
|
3086
3115
|
|
|
3116
|
+
// src/utils/cli-utils.ts
|
|
3117
|
+
function getElapsedTime(startTime) {
|
|
3118
|
+
return ((Date.now() - startTime) / 1e3).toFixed(2);
|
|
3119
|
+
}
|
|
3120
|
+
function handleCLIError(error, commandName) {
|
|
3121
|
+
console.error(`\u274C ${commandName} failed:`, error);
|
|
3122
|
+
process.exit(1);
|
|
3123
|
+
}
|
|
3124
|
+
|
|
3125
|
+
// src/utils/cli-helpers.ts
|
|
3126
|
+
async function loadMergedConfig(directory, defaults, cliOptions) {
|
|
3127
|
+
const config = await loadConfig(directory);
|
|
3128
|
+
const mergedConfig = mergeConfigWithDefaults(config, defaults);
|
|
3129
|
+
const result = {
|
|
3130
|
+
...mergedConfig,
|
|
3131
|
+
...cliOptions,
|
|
3132
|
+
rootDir: directory
|
|
3133
|
+
};
|
|
3134
|
+
return result;
|
|
3135
|
+
}
|
|
3136
|
+
|
|
3087
3137
|
// src/utils/cli-action-helpers.ts
|
|
3088
3138
|
var import_path3 = require("path");
|
|
3089
3139
|
function getReportTimestamp() {
|
|
@@ -3675,6 +3725,9 @@ function mergeConfigWithDefaults(userConfig, defaults) {
|
|
|
3675
3725
|
if (userConfig.scan.include) mergedConfig.include = userConfig.scan.include;
|
|
3676
3726
|
if (userConfig.scan.exclude) mergedConfig.exclude = userConfig.scan.exclude;
|
|
3677
3727
|
}
|
|
3728
|
+
if (userConfig.threshold !== void 0)
|
|
3729
|
+
mergedConfig.threshold = userConfig.threshold;
|
|
3730
|
+
if (userConfig.failOn !== void 0) mergedConfig.failOn = userConfig.failOn;
|
|
3678
3731
|
if (userConfig.tools) {
|
|
3679
3732
|
if (!mergedConfig.toolConfigs) mergedConfig.toolConfigs = {};
|
|
3680
3733
|
for (const [toolName, toolConfig] of Object.entries(userConfig.tools)) {
|
|
@@ -3858,114 +3911,148 @@ function generateHTML(graph) {
|
|
|
3858
3911
|
</html>`;
|
|
3859
3912
|
}
|
|
3860
3913
|
|
|
3914
|
+
// src/utils/report-styles.ts
|
|
3915
|
+
var REPORT_STYLES = `
|
|
3916
|
+
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; line-height: 1.6; color: #333; max-width: 1200px; margin: 0 auto; padding: 2rem; background-color: #f9f9f9; }
|
|
3917
|
+
h1, h2, h3 { color: #1a1a1a; border-bottom: 2px solid #eaeaea; padding-bottom: 0.5rem; }
|
|
3918
|
+
.card { background: white; padding: 1.5rem; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.05); margin-bottom: 2rem; border: 1px solid #eaeaea; }
|
|
3919
|
+
.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 1rem; margin-bottom: 2rem; }
|
|
3920
|
+
.stat-card { background: #fff; padding: 1rem; border-radius: 6px; text-align: center; border: 1px solid #eaeaea; }
|
|
3921
|
+
.stat-value { font-size: 1.8rem; font-weight: bold; color: #2563eb; }
|
|
3922
|
+
.stat-label { font-size: 0.875rem; color: #666; text-transform: uppercase; }
|
|
3923
|
+
.hero { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 30px; border-radius: 8px; margin-bottom: 30px; }
|
|
3924
|
+
.hero h1 { border: none; color: white; margin: 0; }
|
|
3925
|
+
.hero p { margin: 10px 0 0 0; opacity: 0.9; }
|
|
3926
|
+
table { width: 100%; border-collapse: collapse; margin-top: 1rem; background: white; border-radius: 4px; overflow: hidden; }
|
|
3927
|
+
th, td { text-align: left; padding: 0.875rem 1rem; border-bottom: 1px solid #eaeaea; }
|
|
3928
|
+
th { background-color: #f8fafc; font-weight: 600; color: #475569; }
|
|
3929
|
+
tr:last-child td { border-bottom: none; }
|
|
3930
|
+
.critical { color: #dc2626; font-weight: bold; }
|
|
3931
|
+
.major { color: #ea580c; font-weight: bold; }
|
|
3932
|
+
.minor { color: #2563eb; }
|
|
3933
|
+
.issue-critical { color: #dc2626; font-weight: bold; text-transform: uppercase; }
|
|
3934
|
+
.issue-major { color: #ea580c; font-weight: bold; text-transform: uppercase; }
|
|
3935
|
+
.issue-minor { color: #2563eb; font-weight: bold; text-transform: uppercase; }
|
|
3936
|
+
code { background: #f1f5f9; padding: 0.2rem 0.4rem; border-radius: 4px; font-size: 0.875rem; color: #334155; }
|
|
3937
|
+
.footer { margin-top: 4rem; text-align: center; color: #94a3b8; font-size: 0.875rem; }
|
|
3938
|
+
a { color: #2563eb; text-decoration: none; }
|
|
3939
|
+
a:hover { text-decoration: underline; }
|
|
3940
|
+
`;
|
|
3941
|
+
|
|
3861
3942
|
// src/utils/report-formatters.ts
|
|
3862
|
-
function
|
|
3943
|
+
function tag(name, content = "", attrs = {}) {
|
|
3944
|
+
const attrStr = Object.entries(attrs).map(([k, v]) => ` ${k}="${v}"`).join("");
|
|
3945
|
+
return `<${name}${attrStr}>${content}</${name}>`;
|
|
3946
|
+
}
|
|
3947
|
+
function generateReportHead(title, styles = REPORT_STYLES) {
|
|
3863
3948
|
return `<!DOCTYPE html>
|
|
3864
3949
|
<html lang="en">
|
|
3865
3950
|
<head>
|
|
3866
3951
|
<meta charset="UTF-8">
|
|
3867
3952
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
3868
|
-
|
|
3869
|
-
|
|
3870
|
-
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; line-height: 1.6; color: #333; max-width: 1200px; margin: 0 auto; padding: 2rem; background-color: #f9f9f9; }
|
|
3871
|
-
h1, h2, h3 { color: #1a1a1a; border-bottom: 2px solid #eaeaea; padding-bottom: 0.5rem; }
|
|
3872
|
-
.card { background: white; padding: 1.5rem; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.05); margin-bottom: 2rem; border: 1px solid #eaeaea; }
|
|
3873
|
-
.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 1rem; margin-bottom: 2rem; }
|
|
3874
|
-
.stat-card { background: #fff; padding: 1rem; border-radius: 6px; text-align: center; border: 1px solid #eaeaea; }
|
|
3875
|
-
.stat-value { font-size: 1.8rem; font-weight: bold; color: #2563eb; }
|
|
3876
|
-
.stat-label { font-size: 0.875rem; color: #666; text-transform: uppercase; }
|
|
3877
|
-
.hero { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 30px; border-radius: 8px; margin-bottom: 30px; }
|
|
3878
|
-
.hero h1 { border: none; color: white; margin: 0; }
|
|
3879
|
-
.hero p { margin: 10px 0 0 0; opacity: 0.9; }
|
|
3880
|
-
table { width: 100%; border-collapse: collapse; margin-top: 1rem; background: white; border-radius: 4px; overflow: hidden; }
|
|
3881
|
-
th, td { text-align: left; padding: 0.875rem 1rem; border-bottom: 1px solid #eaeaea; }
|
|
3882
|
-
th { background-color: #f8fafc; font-weight: 600; color: #475569; }
|
|
3883
|
-
tr:last-child td { border-bottom: none; }
|
|
3884
|
-
.critical { color: #dc2626; font-weight: bold; }
|
|
3885
|
-
.major { color: #ea580c; font-weight: bold; }
|
|
3886
|
-
.minor { color: #2563eb; }
|
|
3887
|
-
.issue-critical { color: #dc2626; font-weight: bold; text-transform: uppercase; }
|
|
3888
|
-
.issue-major { color: #ea580c; font-weight: bold; text-transform: uppercase; }
|
|
3889
|
-
.issue-minor { color: #2563eb; font-weight: bold; text-transform: uppercase; }
|
|
3890
|
-
code { background: #f1f5f9; padding: 0.2rem 0.4rem; border-radius: 4px; font-size: 0.875rem; color: #334155; }
|
|
3891
|
-
.footer { margin-top: 4rem; text-align: center; color: #94a3b8; font-size: 0.875rem; }
|
|
3892
|
-
a { color: #2563eb; text-decoration: none; }
|
|
3893
|
-
a:hover { text-decoration: underline; }
|
|
3894
|
-
</style>
|
|
3953
|
+
${tag("title", title)}
|
|
3954
|
+
${tag("style", styles)}
|
|
3895
3955
|
</head>`;
|
|
3896
3956
|
}
|
|
3897
3957
|
function generateReportHero(title, subtitle) {
|
|
3898
|
-
|
|
3899
|
-
|
|
3900
|
-
|
|
3901
|
-
${subtitleHtml}
|
|
3902
|
-
</div>`;
|
|
3958
|
+
return tag("div", tag("h1", title) + (subtitle ? tag("p", subtitle) : ""), {
|
|
3959
|
+
class: "hero"
|
|
3960
|
+
});
|
|
3903
3961
|
}
|
|
3904
3962
|
function generateStatCards(cards) {
|
|
3905
3963
|
const cardsHtml = cards.map(
|
|
3906
|
-
(
|
|
3907
|
-
|
|
3908
|
-
|
|
3909
|
-
|
|
3910
|
-
|
|
3964
|
+
(c) => tag(
|
|
3965
|
+
"div",
|
|
3966
|
+
tag("div", String(c.value), {
|
|
3967
|
+
class: "stat-value",
|
|
3968
|
+
...c.color ? { style: `color: ${c.color}` } : {}
|
|
3969
|
+
}) + tag("div", c.label, { class: "stat-label" }),
|
|
3970
|
+
{ class: "stat-card" }
|
|
3971
|
+
)
|
|
3911
3972
|
).join("");
|
|
3912
|
-
return
|
|
3913
|
-
}
|
|
3914
|
-
function generateScoreCard(value, label) {
|
|
3915
|
-
return `<div class="stat-card" style="margin-bottom: 2rem;">
|
|
3916
|
-
<div class="stat-label">${label}</div>
|
|
3917
|
-
<div class="stat-value">${value}</div>
|
|
3918
|
-
</div>`;
|
|
3973
|
+
return tag("div", cardsHtml, { class: "stats" });
|
|
3919
3974
|
}
|
|
3920
3975
|
function generateTable(config) {
|
|
3921
|
-
const
|
|
3922
|
-
|
|
3923
|
-
|
|
3924
|
-
|
|
3925
|
-
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
|
|
3929
|
-
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
|
|
3933
|
-
|
|
3934
|
-
|
|
3935
|
-
|
|
3936
|
-
|
|
3937
|
-
${
|
|
3938
|
-
|
|
3976
|
+
const head = tag(
|
|
3977
|
+
"thead",
|
|
3978
|
+
tag("tr", config.headers.map((h) => tag("th", h)).join(""))
|
|
3979
|
+
);
|
|
3980
|
+
const body = tag(
|
|
3981
|
+
"tbody",
|
|
3982
|
+
config.rows.map(
|
|
3983
|
+
(row) => tag("tr", row.map((cell) => tag("td", cell)).join(""))
|
|
3984
|
+
).join("")
|
|
3985
|
+
);
|
|
3986
|
+
return tag("table", head + body);
|
|
3987
|
+
}
|
|
3988
|
+
function generateIssueSummary(crit, maj, min, savings) {
|
|
3989
|
+
const details = [
|
|
3990
|
+
tag("span", `\u{1F534} Critical: ${crit}`, { class: "critical" }),
|
|
3991
|
+
tag("span", `\u{1F7E1} Major: ${maj}`, { class: "major" }),
|
|
3992
|
+
tag("span", `\u{1F535} Minor: ${min}`, { class: "minor" })
|
|
3993
|
+
].join(" ");
|
|
3994
|
+
const savingsHtml = savings ? tag(
|
|
3995
|
+
"p",
|
|
3996
|
+
tag("strong", "Potential Savings: ") + savings.toLocaleString() + " tokens"
|
|
3997
|
+
) : "";
|
|
3998
|
+
return tag(
|
|
3999
|
+
"div",
|
|
4000
|
+
tag("h2", "\u26A0\uFE0F Issues Summary") + tag("p", details) + savingsHtml,
|
|
4001
|
+
{ class: "card", style: "margin-bottom: 30px;" }
|
|
4002
|
+
);
|
|
3939
4003
|
}
|
|
3940
4004
|
function generateReportFooter(options) {
|
|
3941
|
-
const
|
|
4005
|
+
const version = options.version ? ` v${options.version}` : "";
|
|
3942
4006
|
const links = [];
|
|
3943
|
-
if (options.packageUrl)
|
|
3944
|
-
links.push(
|
|
3945
|
-
|
|
3946
|
-
|
|
3947
|
-
|
|
3948
|
-
|
|
3949
|
-
|
|
3950
|
-
|
|
3951
|
-
|
|
3952
|
-
|
|
3953
|
-
|
|
4007
|
+
if (options.packageUrl)
|
|
4008
|
+
links.push(
|
|
4009
|
+
tag(
|
|
4010
|
+
"p",
|
|
4011
|
+
`Like AIReady? ${tag("a", "Star us on GitHub", { href: options.packageUrl })}`
|
|
4012
|
+
)
|
|
4013
|
+
);
|
|
4014
|
+
if (options.bugUrl)
|
|
4015
|
+
links.push(
|
|
4016
|
+
tag(
|
|
4017
|
+
"p",
|
|
4018
|
+
`Like AIReady? ${tag("a", "Report it here", { href: options.bugUrl })}`
|
|
4019
|
+
)
|
|
4020
|
+
);
|
|
4021
|
+
return tag(
|
|
4022
|
+
"div",
|
|
4023
|
+
tag(
|
|
4024
|
+
"p",
|
|
4025
|
+
`Generated by ${tag("strong", "@aiready/" + options.packageName)}` + version
|
|
4026
|
+
) + links.join(""),
|
|
4027
|
+
{ class: "footer" }
|
|
4028
|
+
);
|
|
3954
4029
|
}
|
|
3955
4030
|
function wrapInCard(content, title) {
|
|
3956
|
-
|
|
3957
|
-
|
|
3958
|
-
|
|
3959
|
-
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
|
|
3964
|
-
|
|
3965
|
-
|
|
3966
|
-
|
|
3967
|
-
|
|
3968
|
-
|
|
4031
|
+
return tag("div", (title ? tag("h2", title) : "") + content, {
|
|
4032
|
+
class: "card"
|
|
4033
|
+
});
|
|
4034
|
+
}
|
|
4035
|
+
function generateCompleteReport(options, body) {
|
|
4036
|
+
return generateReportHead(options.title) + tag("body", body + generateReportFooter(options));
|
|
4037
|
+
}
|
|
4038
|
+
function generateStandardHtmlReport(options, stats, sections, score) {
|
|
4039
|
+
const hero = generateReportHero(
|
|
4040
|
+
`${options.emoji || "\u{1F50D}"} AIReady ${options.title}`,
|
|
4041
|
+
`Generated on ${(/* @__PURE__ */ new Date()).toLocaleString()}`
|
|
4042
|
+
);
|
|
4043
|
+
const scoreCard = score ? tag(
|
|
4044
|
+
"div",
|
|
4045
|
+
tag("div", String(score.value), { class: "score-value" }) + tag("div", score.label, { class: "score-label" }),
|
|
4046
|
+
{ class: "score-card" }
|
|
4047
|
+
) : "";
|
|
4048
|
+
const statsCards = generateStatCards(stats);
|
|
4049
|
+
const bodyContent = `
|
|
4050
|
+
${hero}
|
|
4051
|
+
${scoreCard}
|
|
4052
|
+
${statsCards}
|
|
4053
|
+
${sections.map((s) => wrapInCard(s.content, s.title)).join("\n")}
|
|
4054
|
+
`;
|
|
4055
|
+
return generateCompleteReport(options, bodyContent);
|
|
3969
4056
|
}
|
|
3970
4057
|
|
|
3971
4058
|
// src/utils/rating-helpers.ts
|
|
@@ -4387,12 +4474,12 @@ function calculateHeuristicConfidence(similarity, tokens, lines) {
|
|
|
4387
4474
|
}
|
|
4388
4475
|
|
|
4389
4476
|
// src/utils/cli-factory.ts
|
|
4390
|
-
var
|
|
4477
|
+
var import_chalk4 = __toESM(require("chalk"));
|
|
4391
4478
|
function createStandardProgressCallback(toolName) {
|
|
4392
4479
|
return (processed, total, message) => {
|
|
4393
4480
|
const percent = Math.round(processed / Math.max(1, total) * 100);
|
|
4394
4481
|
process.stdout.write(
|
|
4395
|
-
`\r\x1B[K [${toolName}] ${
|
|
4482
|
+
`\r\x1B[K [${toolName}] ${import_chalk4.default.cyan(`${percent}%`)} ${message}`
|
|
4396
4483
|
);
|
|
4397
4484
|
if (processed === total) {
|
|
4398
4485
|
process.stdout.write("\n");
|
|
@@ -4400,12 +4487,12 @@ function createStandardProgressCallback(toolName) {
|
|
|
4400
4487
|
};
|
|
4401
4488
|
}
|
|
4402
4489
|
function formatStandardCliResult(toolName, score, issuesCount) {
|
|
4403
|
-
const scoreColor = score >= 75 ?
|
|
4490
|
+
const scoreColor = score >= 75 ? import_chalk4.default.green : score >= 50 ? import_chalk4.default.yellow : import_chalk4.default.red;
|
|
4404
4491
|
console.log(`
|
|
4405
|
-
${
|
|
4492
|
+
${import_chalk4.default.bold(toolName.toUpperCase())} Analysis Complete`);
|
|
4406
4493
|
console.log(` Overall Score: ${scoreColor(score)}/100`);
|
|
4407
4494
|
console.log(
|
|
4408
|
-
` Issues Found: ${issuesCount > 0 ?
|
|
4495
|
+
` Issues Found: ${issuesCount > 0 ? import_chalk4.default.red(issuesCount) : import_chalk4.default.green("None")}`
|
|
4409
4496
|
);
|
|
4410
4497
|
}
|
|
4411
4498
|
async function runStandardCliAction(toolName, action) {
|
|
@@ -4414,7 +4501,7 @@ async function runStandardCliAction(toolName, action) {
|
|
|
4414
4501
|
formatStandardCliResult(toolName, score, issuesCount);
|
|
4415
4502
|
} catch (error) {
|
|
4416
4503
|
console.error(
|
|
4417
|
-
|
|
4504
|
+
import_chalk4.default.red(`
|
|
4418
4505
|
\u274C [${toolName}] critical error: ${error.message}`)
|
|
4419
4506
|
);
|
|
4420
4507
|
process.exit(1);
|
|
@@ -4422,13 +4509,13 @@ async function runStandardCliAction(toolName, action) {
|
|
|
4422
4509
|
}
|
|
4423
4510
|
|
|
4424
4511
|
// src/utils/reporting.ts
|
|
4425
|
-
var
|
|
4512
|
+
var import_chalk5 = __toESM(require("chalk"));
|
|
4426
4513
|
function getScoreColor(score) {
|
|
4427
|
-
if (score >= 85) return
|
|
4428
|
-
if (score >= 70) return
|
|
4429
|
-
if (score >= 50) return
|
|
4430
|
-
if (score >= 30) return
|
|
4431
|
-
return
|
|
4514
|
+
if (score >= 85) return import_chalk5.default.green;
|
|
4515
|
+
if (score >= 70) return import_chalk5.default.cyan;
|
|
4516
|
+
if (score >= 50) return import_chalk5.default.yellow;
|
|
4517
|
+
if (score >= 30) return import_chalk5.default.red;
|
|
4518
|
+
return import_chalk5.default.bgRed.white;
|
|
4432
4519
|
}
|
|
4433
4520
|
function displayStandardConsoleReport(data) {
|
|
4434
4521
|
const {
|
|
@@ -4443,27 +4530,27 @@ function displayStandardConsoleReport(data) {
|
|
|
4443
4530
|
noIssuesMessage = "\u2728 No issues found!",
|
|
4444
4531
|
safetyRating
|
|
4445
4532
|
} = data;
|
|
4446
|
-
console.log(
|
|
4533
|
+
console.log(import_chalk5.default.bold(`
|
|
4447
4534
|
${title}
|
|
4448
4535
|
`));
|
|
4449
4536
|
if (safetyRating) {
|
|
4450
4537
|
if (safetyRating === "blind-risk" || safetyRating === "\u{1F480} blind-risk") {
|
|
4451
4538
|
console.log(
|
|
4452
|
-
|
|
4539
|
+
import_chalk5.default.bgRed.white.bold(
|
|
4453
4540
|
" \u{1F480} BLIND RISK \u2014 NO TESTS DETECTED. AI-GENERATED CHANGES CANNOT BE VERIFIED. "
|
|
4454
4541
|
)
|
|
4455
4542
|
);
|
|
4456
4543
|
console.log();
|
|
4457
4544
|
} else if (safetyRating === "high-risk" || safetyRating === "\u{1F534} high-risk") {
|
|
4458
4545
|
console.log(
|
|
4459
|
-
|
|
4546
|
+
import_chalk5.default.red.bold(
|
|
4460
4547
|
` \u{1F534} HIGH RISK \u2014 Insufficient test coverage. AI changes may introduce silent bugs.`
|
|
4461
4548
|
)
|
|
4462
4549
|
);
|
|
4463
4550
|
console.log();
|
|
4464
4551
|
}
|
|
4465
4552
|
}
|
|
4466
|
-
const safetyColor = safetyRating ? getSeverityColor(safetyRating,
|
|
4553
|
+
const safetyColor = safetyRating ? getSeverityColor(safetyRating, import_chalk5.default) : getScoreColor(score);
|
|
4467
4554
|
if (safetyRating) {
|
|
4468
4555
|
console.log(
|
|
4469
4556
|
`AI Change Safety: ${safetyColor(`${getSafetyIcon(safetyRating)} ${safetyRating.toUpperCase()}`)}`
|
|
@@ -4473,12 +4560,12 @@ ${title}
|
|
|
4473
4560
|
`Score: ${getScoreColor(score)(score + "/100")} (${rating.toUpperCase()})`
|
|
4474
4561
|
);
|
|
4475
4562
|
if (stats.length > 0) {
|
|
4476
|
-
const statsStr = stats.map((s) => `${s.label}: ${
|
|
4563
|
+
const statsStr = stats.map((s) => `${s.label}: ${import_chalk5.default.cyan(s.value)}`).join(" ");
|
|
4477
4564
|
console.log(statsStr);
|
|
4478
4565
|
}
|
|
4479
|
-
console.log(`Analysis Time: ${
|
|
4566
|
+
console.log(`Analysis Time: ${import_chalk5.default.gray(elapsedTime + "s")}
|
|
4480
4567
|
`);
|
|
4481
|
-
console.log(
|
|
4568
|
+
console.log(import_chalk5.default.bold("\u{1F4D0} Dimension Scores\n"));
|
|
4482
4569
|
for (const dim of dimensions) {
|
|
4483
4570
|
const color = getScoreColor(dim.value);
|
|
4484
4571
|
console.log(
|
|
@@ -4486,24 +4573,24 @@ ${title}
|
|
|
4486
4573
|
);
|
|
4487
4574
|
}
|
|
4488
4575
|
if (issues.length > 0) {
|
|
4489
|
-
console.log(
|
|
4576
|
+
console.log(import_chalk5.default.bold("\n\u26A0\uFE0F Issues\n"));
|
|
4490
4577
|
for (const issue of issues) {
|
|
4491
|
-
const sev = getSeverityColor(issue.severity,
|
|
4578
|
+
const sev = getSeverityColor(issue.severity, import_chalk5.default);
|
|
4492
4579
|
console.log(`${sev(issue.severity.toUpperCase())} ${issue.message}`);
|
|
4493
4580
|
if (issue.suggestion) {
|
|
4494
4581
|
console.log(
|
|
4495
|
-
` ${
|
|
4582
|
+
` ${import_chalk5.default.dim("\u2192")} ${import_chalk5.default.italic(issue.suggestion)}`
|
|
4496
4583
|
);
|
|
4497
4584
|
}
|
|
4498
4585
|
console.log();
|
|
4499
4586
|
}
|
|
4500
4587
|
} else {
|
|
4501
|
-
console.log(
|
|
4588
|
+
console.log(import_chalk5.default.green(`
|
|
4502
4589
|
${noIssuesMessage}
|
|
4503
4590
|
`));
|
|
4504
4591
|
}
|
|
4505
4592
|
if (recommendations.length > 0) {
|
|
4506
|
-
console.log(
|
|
4593
|
+
console.log(import_chalk5.default.bold("\u{1F4A1} Recommendations\n"));
|
|
4507
4594
|
recommendations.forEach((rec, i) => {
|
|
4508
4595
|
console.log(`${i + 1}. ${rec}`);
|
|
4509
4596
|
});
|
|
@@ -5492,7 +5579,17 @@ function calculateAiSignalClarity(params) {
|
|
|
5492
5579
|
rating: "minimal",
|
|
5493
5580
|
signals: [],
|
|
5494
5581
|
topRisk: "No symbols to analyze",
|
|
5495
|
-
recommendations: []
|
|
5582
|
+
recommendations: [],
|
|
5583
|
+
dimensions: {
|
|
5584
|
+
overloadingScore: 100,
|
|
5585
|
+
magicLiteralScore: 100,
|
|
5586
|
+
booleanTrapScore: 100,
|
|
5587
|
+
implicitSideEffectScore: 100,
|
|
5588
|
+
deepCallbackScore: 100,
|
|
5589
|
+
ambiguityScore: 100,
|
|
5590
|
+
documentationScore: 100,
|
|
5591
|
+
sizeScore: 100
|
|
5592
|
+
}
|
|
5496
5593
|
};
|
|
5497
5594
|
}
|
|
5498
5595
|
const overloadRatio = overloadedSymbols / Math.max(1, totalSymbols);
|
|
@@ -5605,7 +5702,23 @@ function calculateAiSignalClarity(params) {
|
|
|
5605
5702
|
rating,
|
|
5606
5703
|
signals: signals.filter((s) => s.count > 0),
|
|
5607
5704
|
topRisk,
|
|
5608
|
-
recommendations
|
|
5705
|
+
recommendations,
|
|
5706
|
+
dimensions: {
|
|
5707
|
+
overloadingScore: Math.max(0, 100 - overloadSignal.riskContribution * 5),
|
|
5708
|
+
magicLiteralScore: Math.max(0, 100 - magicSignal.riskContribution * 6.6),
|
|
5709
|
+
booleanTrapScore: Math.max(0, 100 - trapSignal.riskContribution * 6.6),
|
|
5710
|
+
implicitSideEffectScore: Math.max(
|
|
5711
|
+
0,
|
|
5712
|
+
100 - sideEffectSignal.riskContribution * 10
|
|
5713
|
+
),
|
|
5714
|
+
deepCallbackScore: Math.max(
|
|
5715
|
+
0,
|
|
5716
|
+
100 - callbackSignal.riskContribution * 10
|
|
5717
|
+
),
|
|
5718
|
+
ambiguityScore: Math.max(0, 100 - ambiguousSignal.riskContribution * 20),
|
|
5719
|
+
documentationScore: Math.max(0, 100 - undocSignal.riskContribution * 20),
|
|
5720
|
+
sizeScore: Math.max(0, 100 - largeFileSignal.riskContribution * 4)
|
|
5721
|
+
}
|
|
5609
5722
|
};
|
|
5610
5723
|
}
|
|
5611
5724
|
|
|
@@ -6208,6 +6321,104 @@ function emitIssuesAsAnnotations(issues) {
|
|
|
6208
6321
|
});
|
|
6209
6322
|
});
|
|
6210
6323
|
}
|
|
6324
|
+
|
|
6325
|
+
// src/utils/analysis-orchestrator.ts
|
|
6326
|
+
async function runBatchAnalysis(items, label, toolId, onProgress, processFn, onResult) {
|
|
6327
|
+
let processed = 0;
|
|
6328
|
+
for (const item of items) {
|
|
6329
|
+
processed++;
|
|
6330
|
+
emitProgress(processed, items.length, toolId, label, onProgress);
|
|
6331
|
+
const result = await processFn(item);
|
|
6332
|
+
onResult(result);
|
|
6333
|
+
}
|
|
6334
|
+
}
|
|
6335
|
+
|
|
6336
|
+
// src/utils/spoke-cli-helpers.ts
|
|
6337
|
+
var import_chalk6 = __toESM(require("chalk"));
|
|
6338
|
+
async function executeSpokeCli(name, description, options, analyzeFn) {
|
|
6339
|
+
console.log(import_chalk6.default.cyan(`Analyzing ${description.toLowerCase()}...`));
|
|
6340
|
+
try {
|
|
6341
|
+
const report = await analyzeFn({
|
|
6342
|
+
rootDir: process.cwd(),
|
|
6343
|
+
...options
|
|
6344
|
+
});
|
|
6345
|
+
console.log(import_chalk6.default.bold(`
|
|
6346
|
+
${name} Analysis Results:`));
|
|
6347
|
+
console.log(
|
|
6348
|
+
`Rating: ${report.summary.rating.toUpperCase()} (Score: ${report.summary.score})`
|
|
6349
|
+
);
|
|
6350
|
+
if (report.issues && report.issues.length > 0) {
|
|
6351
|
+
console.log(import_chalk6.default.red(`
|
|
6352
|
+
Found ${report.issues.length} issues.`));
|
|
6353
|
+
} else {
|
|
6354
|
+
console.log(import_chalk6.default.green("\nNo issues detected."));
|
|
6355
|
+
}
|
|
6356
|
+
return report;
|
|
6357
|
+
} catch (err) {
|
|
6358
|
+
console.error(import_chalk6.default.red(`Error during ${name} analysis: ${err.message}`));
|
|
6359
|
+
process.exit(1);
|
|
6360
|
+
}
|
|
6361
|
+
}
|
|
6362
|
+
|
|
6363
|
+
// src/utils/test-utils.ts
|
|
6364
|
+
var import_fs5 = require("fs");
|
|
6365
|
+
var import_path6 = require("path");
|
|
6366
|
+
var TEST_PATTERNS = [
|
|
6367
|
+
/\.(test|spec)\.(ts|tsx|js|jsx)$/,
|
|
6368
|
+
/_test\.go$/,
|
|
6369
|
+
/test_.*\.py$/,
|
|
6370
|
+
/.*_test\.py$/,
|
|
6371
|
+
/.*Test\.java$/,
|
|
6372
|
+
/.*Tests\.cs$/,
|
|
6373
|
+
/__tests__\//,
|
|
6374
|
+
/\/tests?\//,
|
|
6375
|
+
/\/e2e\//,
|
|
6376
|
+
/\/fixtures\//
|
|
6377
|
+
];
|
|
6378
|
+
function isTestFile(filePath, extraPatterns) {
|
|
6379
|
+
if (TEST_PATTERNS.some((p) => p.test(filePath))) return true;
|
|
6380
|
+
if (extraPatterns) return extraPatterns.some((p) => filePath.includes(p));
|
|
6381
|
+
return false;
|
|
6382
|
+
}
|
|
6383
|
+
function detectTestFramework(rootDir) {
|
|
6384
|
+
const manifests = [
|
|
6385
|
+
{
|
|
6386
|
+
file: "package.json",
|
|
6387
|
+
deps: [
|
|
6388
|
+
"jest",
|
|
6389
|
+
"vitest",
|
|
6390
|
+
"mocha",
|
|
6391
|
+
"jasmine",
|
|
6392
|
+
"ava",
|
|
6393
|
+
"tap",
|
|
6394
|
+
"playwright",
|
|
6395
|
+
"cypress"
|
|
6396
|
+
]
|
|
6397
|
+
},
|
|
6398
|
+
{ file: "requirements.txt", deps: ["pytest", "unittest", "nose"] },
|
|
6399
|
+
{ file: "pyproject.toml", deps: ["pytest"] },
|
|
6400
|
+
{ file: "pom.xml", deps: ["junit", "testng"] },
|
|
6401
|
+
{ file: "build.gradle", deps: ["junit", "testng"] },
|
|
6402
|
+
{ file: "go.mod", deps: ["testing"] }
|
|
6403
|
+
// go testing is built-in
|
|
6404
|
+
];
|
|
6405
|
+
for (const m of manifests) {
|
|
6406
|
+
const p = (0, import_path6.join)(rootDir, m.file);
|
|
6407
|
+
if ((0, import_fs5.existsSync)(p)) {
|
|
6408
|
+
if (m.file === "go.mod") return true;
|
|
6409
|
+
try {
|
|
6410
|
+
const content = (0, import_fs5.readFileSync)(p, "utf-8");
|
|
6411
|
+
if (m.deps.some((d) => content.includes(d))) return true;
|
|
6412
|
+
} catch {
|
|
6413
|
+
}
|
|
6414
|
+
}
|
|
6415
|
+
}
|
|
6416
|
+
return false;
|
|
6417
|
+
}
|
|
6418
|
+
function isBuildArtifact(filePath) {
|
|
6419
|
+
const lower = filePath.toLowerCase();
|
|
6420
|
+
return lower.includes("/node_modules/") || lower.includes("/dist/") || lower.includes("/build/") || lower.includes("/out/") || lower.includes("/.next/") || lower.includes("/target/") || lower.includes("/bin/");
|
|
6421
|
+
}
|
|
6211
6422
|
// Annotate the CommonJS export names for ESM import in node:
|
|
6212
6423
|
0 && (module.exports = {
|
|
6213
6424
|
AIReadyConfigSchema,
|
|
@@ -6253,6 +6464,7 @@ function emitIssuesAsAnnotations(issues) {
|
|
|
6253
6464
|
SeveritySchema,
|
|
6254
6465
|
SpokeOutputSchema,
|
|
6255
6466
|
SpokeSummarySchema,
|
|
6467
|
+
TEST_PATTERNS,
|
|
6256
6468
|
TOOL_NAME_MAP,
|
|
6257
6469
|
ToolName,
|
|
6258
6470
|
ToolNameSchema,
|
|
@@ -6292,14 +6504,18 @@ function emitIssuesAsAnnotations(issues) {
|
|
|
6292
6504
|
clearHistory,
|
|
6293
6505
|
createProvider,
|
|
6294
6506
|
createStandardProgressCallback,
|
|
6507
|
+
detectTestFramework,
|
|
6295
6508
|
displayStandardConsoleReport,
|
|
6296
6509
|
emitAnnotation,
|
|
6297
6510
|
emitIssuesAsAnnotations,
|
|
6298
6511
|
emitProgress,
|
|
6512
|
+
ensureDir,
|
|
6299
6513
|
estimateCostFromBudget,
|
|
6300
6514
|
estimateTokens,
|
|
6515
|
+
executeSpokeCli,
|
|
6301
6516
|
exportHistory,
|
|
6302
6517
|
extractCodeBlocks,
|
|
6518
|
+
filterBySeverity,
|
|
6303
6519
|
findLatestReport,
|
|
6304
6520
|
findLatestScanReport,
|
|
6305
6521
|
formatAcceptanceRate,
|
|
@@ -6315,13 +6531,14 @@ function emitIssuesAsAnnotations(issues) {
|
|
|
6315
6531
|
generateReportFooter,
|
|
6316
6532
|
generateReportHead,
|
|
6317
6533
|
generateReportHero,
|
|
6318
|
-
|
|
6534
|
+
generateStandardHtmlReport,
|
|
6319
6535
|
generateStatCards,
|
|
6320
6536
|
generateTable,
|
|
6321
6537
|
generateValueChain,
|
|
6322
6538
|
getElapsedTime,
|
|
6323
6539
|
getFileCommitTimestamps,
|
|
6324
6540
|
getFileExtension,
|
|
6541
|
+
getFilesByPattern,
|
|
6325
6542
|
getHistorySummary,
|
|
6326
6543
|
getLineRangeLastModifiedCached,
|
|
6327
6544
|
getModelPreset,
|
|
@@ -6344,6 +6561,7 @@ function emitIssuesAsAnnotations(issues) {
|
|
|
6344
6561
|
getSeverityBadge,
|
|
6345
6562
|
getSeverityColor,
|
|
6346
6563
|
getSeverityEnum,
|
|
6564
|
+
getSeverityLabel,
|
|
6347
6565
|
getSeverityLevel,
|
|
6348
6566
|
getSeverityValue,
|
|
6349
6567
|
getSupportedLanguages,
|
|
@@ -6358,8 +6576,10 @@ function emitIssuesAsAnnotations(issues) {
|
|
|
6358
6576
|
inferPatternType,
|
|
6359
6577
|
initTreeSitter,
|
|
6360
6578
|
initializeParsers,
|
|
6579
|
+
isBuildArtifact,
|
|
6361
6580
|
isFileSupported,
|
|
6362
6581
|
isSourceFile,
|
|
6582
|
+
isTestFile,
|
|
6363
6583
|
loadConfig,
|
|
6364
6584
|
loadMergedConfig,
|
|
6365
6585
|
loadScoreHistory,
|
|
@@ -6367,6 +6587,7 @@ function emitIssuesAsAnnotations(issues) {
|
|
|
6367
6587
|
normalizeAnalysisResult,
|
|
6368
6588
|
normalizeIssue,
|
|
6369
6589
|
normalizeMetrics,
|
|
6590
|
+
normalizeSeverity,
|
|
6370
6591
|
normalizeSpokeOutput,
|
|
6371
6592
|
normalizeToolName,
|
|
6372
6593
|
parseFileExports,
|
|
@@ -6377,6 +6598,7 @@ function emitIssuesAsAnnotations(issues) {
|
|
|
6377
6598
|
readFileContent,
|
|
6378
6599
|
resolveOutputFormat,
|
|
6379
6600
|
resolveOutputPath,
|
|
6601
|
+
runBatchAnalysis,
|
|
6380
6602
|
runStandardCliAction,
|
|
6381
6603
|
saveScoreEntry,
|
|
6382
6604
|
scanEntries,
|