@getcodesentinel/codesentinel 1.11.0 → 1.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +392 -25
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2463,7 +2463,7 @@ var resolveAutoBaselineRef = async (input) => {
|
|
|
2463
2463
|
|
|
2464
2464
|
// src/index.ts
|
|
2465
2465
|
import { readFileSync as readFileSync2 } from "fs";
|
|
2466
|
-
import { dirname, resolve as resolve5 } from "path";
|
|
2466
|
+
import { dirname as dirname2, resolve as resolve5 } from "path";
|
|
2467
2467
|
import { fileURLToPath } from "url";
|
|
2468
2468
|
|
|
2469
2469
|
// src/application/format-analyze-output.ts
|
|
@@ -2857,6 +2857,337 @@ var parseLogLevel = (value) => {
|
|
|
2857
2857
|
}
|
|
2858
2858
|
};
|
|
2859
2859
|
|
|
2860
|
+
// src/application/check-for-updates.ts
|
|
2861
|
+
import { spawn } from "child_process";
|
|
2862
|
+
import { mkdir, readFile, writeFile } from "fs/promises";
|
|
2863
|
+
import { homedir } from "os";
|
|
2864
|
+
import { dirname, join as join3 } from "path";
|
|
2865
|
+
import { stderr, stdin } from "process";
|
|
2866
|
+
import { clearScreenDown, cursorTo, emitKeypressEvents, moveCursor } from "readline";
|
|
2867
|
+
var UPDATE_CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
|
|
2868
|
+
var UPDATE_CACHE_PATH = join3(homedir(), ".cache", "codesentinel", "update-check.json");
|
|
2869
|
+
var SEMVER_PATTERN = /^(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+)(?:-(?<prerelease>[0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/;
|
|
2870
|
+
var ANSI = {
|
|
2871
|
+
reset: "\x1B[0m",
|
|
2872
|
+
bold: "\x1B[1m",
|
|
2873
|
+
dim: "\x1B[2m",
|
|
2874
|
+
cyan: "\x1B[36m",
|
|
2875
|
+
green: "\x1B[32m",
|
|
2876
|
+
yellow: "\x1B[33m"
|
|
2877
|
+
};
|
|
2878
|
+
var parsePrereleaseIdentifier = (identifier) => {
|
|
2879
|
+
if (/^\d+$/.test(identifier)) {
|
|
2880
|
+
return Number.parseInt(identifier, 10);
|
|
2881
|
+
}
|
|
2882
|
+
return identifier;
|
|
2883
|
+
};
|
|
2884
|
+
var parseSemver2 = (value) => {
|
|
2885
|
+
const match = SEMVER_PATTERN.exec(value.trim());
|
|
2886
|
+
if (match === null) {
|
|
2887
|
+
return null;
|
|
2888
|
+
}
|
|
2889
|
+
const groups = match.groups;
|
|
2890
|
+
if (groups === void 0) {
|
|
2891
|
+
return null;
|
|
2892
|
+
}
|
|
2893
|
+
const majorRaw = groups["major"];
|
|
2894
|
+
const minorRaw = groups["minor"];
|
|
2895
|
+
const patchRaw = groups["patch"];
|
|
2896
|
+
const prereleaseRaw = groups["prerelease"];
|
|
2897
|
+
if (majorRaw === void 0 || minorRaw === void 0 || patchRaw === void 0) {
|
|
2898
|
+
return null;
|
|
2899
|
+
}
|
|
2900
|
+
const prerelease = prereleaseRaw === void 0 || prereleaseRaw.length === 0 ? [] : prereleaseRaw.split(".").map(parsePrereleaseIdentifier);
|
|
2901
|
+
return {
|
|
2902
|
+
major: Number.parseInt(majorRaw, 10),
|
|
2903
|
+
minor: Number.parseInt(minorRaw, 10),
|
|
2904
|
+
patch: Number.parseInt(patchRaw, 10),
|
|
2905
|
+
prerelease
|
|
2906
|
+
};
|
|
2907
|
+
};
|
|
2908
|
+
var comparePrerelease = (left, right) => {
|
|
2909
|
+
if (left.length === 0 && right.length === 0) {
|
|
2910
|
+
return 0;
|
|
2911
|
+
}
|
|
2912
|
+
if (left.length === 0) {
|
|
2913
|
+
return 1;
|
|
2914
|
+
}
|
|
2915
|
+
if (right.length === 0) {
|
|
2916
|
+
return -1;
|
|
2917
|
+
}
|
|
2918
|
+
const length = Math.max(left.length, right.length);
|
|
2919
|
+
for (let index = 0; index < length; index += 1) {
|
|
2920
|
+
const leftValue = left[index];
|
|
2921
|
+
const rightValue = right[index];
|
|
2922
|
+
if (leftValue === void 0) {
|
|
2923
|
+
return -1;
|
|
2924
|
+
}
|
|
2925
|
+
if (rightValue === void 0) {
|
|
2926
|
+
return 1;
|
|
2927
|
+
}
|
|
2928
|
+
if (typeof leftValue === "number" && typeof rightValue === "number") {
|
|
2929
|
+
if (leftValue !== rightValue) {
|
|
2930
|
+
return leftValue > rightValue ? 1 : -1;
|
|
2931
|
+
}
|
|
2932
|
+
continue;
|
|
2933
|
+
}
|
|
2934
|
+
if (typeof leftValue === "number" && typeof rightValue === "string") {
|
|
2935
|
+
return -1;
|
|
2936
|
+
}
|
|
2937
|
+
if (typeof leftValue === "string" && typeof rightValue === "number") {
|
|
2938
|
+
return 1;
|
|
2939
|
+
}
|
|
2940
|
+
if (leftValue !== rightValue) {
|
|
2941
|
+
return leftValue > rightValue ? 1 : -1;
|
|
2942
|
+
}
|
|
2943
|
+
}
|
|
2944
|
+
return 0;
|
|
2945
|
+
};
|
|
2946
|
+
var compareVersions = (left, right) => {
|
|
2947
|
+
const leftParsed = parseSemver2(left);
|
|
2948
|
+
const rightParsed = parseSemver2(right);
|
|
2949
|
+
if (leftParsed === null || rightParsed === null) {
|
|
2950
|
+
return null;
|
|
2951
|
+
}
|
|
2952
|
+
if (leftParsed.major !== rightParsed.major) {
|
|
2953
|
+
return leftParsed.major > rightParsed.major ? 1 : -1;
|
|
2954
|
+
}
|
|
2955
|
+
if (leftParsed.minor !== rightParsed.minor) {
|
|
2956
|
+
return leftParsed.minor > rightParsed.minor ? 1 : -1;
|
|
2957
|
+
}
|
|
2958
|
+
if (leftParsed.patch !== rightParsed.patch) {
|
|
2959
|
+
return leftParsed.patch > rightParsed.patch ? 1 : -1;
|
|
2960
|
+
}
|
|
2961
|
+
return comparePrerelease(leftParsed.prerelease, rightParsed.prerelease);
|
|
2962
|
+
};
|
|
2963
|
+
var isTruthy = (value) => {
|
|
2964
|
+
if (value === void 0) {
|
|
2965
|
+
return false;
|
|
2966
|
+
}
|
|
2967
|
+
return ["1", "true", "yes", "on"].includes(value.trim().toLowerCase());
|
|
2968
|
+
};
|
|
2969
|
+
var parseNpmViewVersionOutput = (output) => {
|
|
2970
|
+
const trimmed = output.trim();
|
|
2971
|
+
if (trimmed.length === 0) {
|
|
2972
|
+
return null;
|
|
2973
|
+
}
|
|
2974
|
+
try {
|
|
2975
|
+
const parsed = JSON.parse(trimmed);
|
|
2976
|
+
if (typeof parsed === "string" && parsed.trim().length > 0) {
|
|
2977
|
+
return parsed.trim();
|
|
2978
|
+
}
|
|
2979
|
+
if (Array.isArray(parsed) && parsed.length > 0) {
|
|
2980
|
+
const latest = parsed.at(-1);
|
|
2981
|
+
if (typeof latest === "string" && latest.trim().length > 0) {
|
|
2982
|
+
return latest.trim();
|
|
2983
|
+
}
|
|
2984
|
+
}
|
|
2985
|
+
} catch {
|
|
2986
|
+
return trimmed;
|
|
2987
|
+
}
|
|
2988
|
+
return null;
|
|
2989
|
+
};
|
|
2990
|
+
var readCache = async () => {
|
|
2991
|
+
try {
|
|
2992
|
+
const raw = await readFile(UPDATE_CACHE_PATH, "utf8");
|
|
2993
|
+
const parsed = JSON.parse(raw);
|
|
2994
|
+
if (typeof parsed === "object" && parsed !== null && typeof parsed.lastCheckedAt === "string") {
|
|
2995
|
+
return { lastCheckedAt: parsed.lastCheckedAt };
|
|
2996
|
+
}
|
|
2997
|
+
} catch {
|
|
2998
|
+
return null;
|
|
2999
|
+
}
|
|
3000
|
+
return null;
|
|
3001
|
+
};
|
|
3002
|
+
var writeCache = async (cache) => {
|
|
3003
|
+
await mkdir(dirname(UPDATE_CACHE_PATH), { recursive: true });
|
|
3004
|
+
await writeFile(UPDATE_CACHE_PATH, JSON.stringify(cache), "utf8");
|
|
3005
|
+
};
|
|
3006
|
+
var shouldRunUpdateCheck = (input) => {
|
|
3007
|
+
if (!input.isInteractive) {
|
|
3008
|
+
return false;
|
|
3009
|
+
}
|
|
3010
|
+
if (isTruthy(input.env["CI"])) {
|
|
3011
|
+
return false;
|
|
3012
|
+
}
|
|
3013
|
+
if (isTruthy(input.env["CODESENTINEL_NO_UPDATE_NOTIFIER"])) {
|
|
3014
|
+
return false;
|
|
3015
|
+
}
|
|
3016
|
+
if (input.argv.some((argument) => argument === "--help" || argument === "-h")) {
|
|
3017
|
+
return false;
|
|
3018
|
+
}
|
|
3019
|
+
if (input.argv.some((argument) => argument === "--version" || argument === "-V")) {
|
|
3020
|
+
return false;
|
|
3021
|
+
}
|
|
3022
|
+
if (input.lastCheckedAt === null) {
|
|
3023
|
+
return true;
|
|
3024
|
+
}
|
|
3025
|
+
const lastCheckedMs = Date.parse(input.lastCheckedAt);
|
|
3026
|
+
if (!Number.isFinite(lastCheckedMs)) {
|
|
3027
|
+
return true;
|
|
3028
|
+
}
|
|
3029
|
+
return input.nowMs - lastCheckedMs >= UPDATE_CHECK_INTERVAL_MS;
|
|
3030
|
+
};
|
|
3031
|
+
var runCommand = async (command, args, mode) => {
|
|
3032
|
+
return await new Promise((resolvePromise, reject) => {
|
|
3033
|
+
const child = spawn(command, [...args], {
|
|
3034
|
+
stdio: mode === "inherit" ? "inherit" : ["ignore", "pipe", "pipe"]
|
|
3035
|
+
});
|
|
3036
|
+
let stdoutRaw = "";
|
|
3037
|
+
if (mode === "capture" && child.stdout !== null) {
|
|
3038
|
+
child.stdout.setEncoding("utf8");
|
|
3039
|
+
child.stdout.on("data", (chunk) => {
|
|
3040
|
+
stdoutRaw += chunk;
|
|
3041
|
+
});
|
|
3042
|
+
}
|
|
3043
|
+
child.on("error", (error) => {
|
|
3044
|
+
reject(error);
|
|
3045
|
+
});
|
|
3046
|
+
child.on("close", (code) => {
|
|
3047
|
+
resolvePromise({ code: code ?? 1, stdout: stdoutRaw });
|
|
3048
|
+
});
|
|
3049
|
+
});
|
|
3050
|
+
};
|
|
3051
|
+
var fetchLatestVersion = async (packageName) => {
|
|
3052
|
+
const result = await runCommand("npm", ["view", packageName, "version", "--json"], "capture");
|
|
3053
|
+
if (result.code !== 0) {
|
|
3054
|
+
return null;
|
|
3055
|
+
}
|
|
3056
|
+
return parseNpmViewVersionOutput(result.stdout);
|
|
3057
|
+
};
|
|
3058
|
+
var renderUpdatePrompt = (latestVersion, currentVersion, selectedIndex) => {
|
|
3059
|
+
const options = ["Install update now", "Not now (continue current command)"];
|
|
3060
|
+
const lines = [
|
|
3061
|
+
`${ANSI.cyan}${ANSI.bold}CodeSentinel Update Available${ANSI.reset}`,
|
|
3062
|
+
`${ANSI.dim}Current: ${currentVersion} Latest: ${latestVersion}${ANSI.reset}`,
|
|
3063
|
+
"",
|
|
3064
|
+
...options.map((option, index) => {
|
|
3065
|
+
const selected = index === selectedIndex;
|
|
3066
|
+
const prefix = selected ? `${ANSI.green}>${ANSI.reset}` : " ";
|
|
3067
|
+
const text = selected ? `${ANSI.bold}${option}${ANSI.reset}` : option;
|
|
3068
|
+
return `${prefix} ${text}`;
|
|
3069
|
+
}),
|
|
3070
|
+
"",
|
|
3071
|
+
`${ANSI.dim}Use \u2191/\u2193 to choose, Enter to confirm.${ANSI.reset}`
|
|
3072
|
+
];
|
|
3073
|
+
stderr.write(lines.join("\n"));
|
|
3074
|
+
return lines.length;
|
|
3075
|
+
};
|
|
3076
|
+
var promptInstall = async (latestVersion, currentVersion) => {
|
|
3077
|
+
if (!stdin.isTTY || !stderr.isTTY || typeof stdin.setRawMode !== "function") {
|
|
3078
|
+
stderr.write(
|
|
3079
|
+
`New version ${latestVersion} is available (current ${currentVersion}). Run: npm install -g @getcodesentinel/codesentinel@latest
|
|
3080
|
+
`
|
|
3081
|
+
);
|
|
3082
|
+
return "skip";
|
|
3083
|
+
}
|
|
3084
|
+
return await new Promise((resolve6) => {
|
|
3085
|
+
emitKeypressEvents(stdin);
|
|
3086
|
+
let selectedIndex = 0;
|
|
3087
|
+
let renderedLines = 0;
|
|
3088
|
+
const previousRawMode = stdin.isRaw;
|
|
3089
|
+
const clearPromptArea = () => {
|
|
3090
|
+
if (renderedLines > 0) {
|
|
3091
|
+
moveCursor(stderr, 0, -(renderedLines - 1));
|
|
3092
|
+
}
|
|
3093
|
+
cursorTo(stderr, 0);
|
|
3094
|
+
clearScreenDown(stderr);
|
|
3095
|
+
};
|
|
3096
|
+
const redraw = () => {
|
|
3097
|
+
clearPromptArea();
|
|
3098
|
+
renderedLines = renderUpdatePrompt(latestVersion, currentVersion, selectedIndex);
|
|
3099
|
+
};
|
|
3100
|
+
const cleanup = (choice) => {
|
|
3101
|
+
stdin.off("keypress", onKeypress);
|
|
3102
|
+
stdin.pause();
|
|
3103
|
+
if (typeof stdin.setRawMode === "function") {
|
|
3104
|
+
stdin.setRawMode(previousRawMode);
|
|
3105
|
+
}
|
|
3106
|
+
clearPromptArea();
|
|
3107
|
+
if (choice === "install") {
|
|
3108
|
+
stderr.write(`${ANSI.yellow}Installing latest CodeSentinel...${ANSI.reset}
|
|
3109
|
+
`);
|
|
3110
|
+
} else if (renderedLines > 0) {
|
|
3111
|
+
stderr.write("\n");
|
|
3112
|
+
}
|
|
3113
|
+
resolve6(choice);
|
|
3114
|
+
};
|
|
3115
|
+
const onKeypress = (_str, key) => {
|
|
3116
|
+
if (key.ctrl === true && key.name === "c") {
|
|
3117
|
+
cleanup("interrupt");
|
|
3118
|
+
return;
|
|
3119
|
+
}
|
|
3120
|
+
if (key.name === "up") {
|
|
3121
|
+
selectedIndex = selectedIndex > 0 ? selectedIndex - 1 : 1;
|
|
3122
|
+
redraw();
|
|
3123
|
+
return;
|
|
3124
|
+
}
|
|
3125
|
+
if (key.name === "down") {
|
|
3126
|
+
selectedIndex = selectedIndex < 1 ? selectedIndex + 1 : 0;
|
|
3127
|
+
redraw();
|
|
3128
|
+
return;
|
|
3129
|
+
}
|
|
3130
|
+
if (key.name === "return" || key.name === "enter") {
|
|
3131
|
+
cleanup(selectedIndex === 0 ? "install" : "skip");
|
|
3132
|
+
}
|
|
3133
|
+
};
|
|
3134
|
+
stdin.on("keypress", onKeypress);
|
|
3135
|
+
if (typeof stdin.setRawMode === "function") {
|
|
3136
|
+
stdin.setRawMode(true);
|
|
3137
|
+
}
|
|
3138
|
+
stdin.resume();
|
|
3139
|
+
redraw();
|
|
3140
|
+
});
|
|
3141
|
+
};
|
|
3142
|
+
var installLatestVersion = async (packageName) => {
|
|
3143
|
+
const result = await runCommand("npm", ["install", "-g", `${packageName}@latest`], "inherit");
|
|
3144
|
+
return result.code === 0;
|
|
3145
|
+
};
|
|
3146
|
+
var checkForCliUpdates = async (input) => {
|
|
3147
|
+
try {
|
|
3148
|
+
const nowMs = Date.now();
|
|
3149
|
+
const cache = await readCache();
|
|
3150
|
+
const shouldCheck = shouldRunUpdateCheck({
|
|
3151
|
+
argv: input.argv,
|
|
3152
|
+
env: input.env,
|
|
3153
|
+
isInteractive: Boolean(process.stdout.isTTY) && Boolean(process.stdin.isTTY),
|
|
3154
|
+
nowMs,
|
|
3155
|
+
lastCheckedAt: cache?.lastCheckedAt ?? null
|
|
3156
|
+
});
|
|
3157
|
+
if (!shouldCheck) {
|
|
3158
|
+
return;
|
|
3159
|
+
}
|
|
3160
|
+
await writeCache({ lastCheckedAt: new Date(nowMs).toISOString() });
|
|
3161
|
+
const latestVersion = await fetchLatestVersion(input.packageName);
|
|
3162
|
+
if (latestVersion === null) {
|
|
3163
|
+
return;
|
|
3164
|
+
}
|
|
3165
|
+
const comparison = compareVersions(latestVersion, input.currentVersion);
|
|
3166
|
+
if (comparison === null || comparison <= 0) {
|
|
3167
|
+
return;
|
|
3168
|
+
}
|
|
3169
|
+
const choice = await promptInstall(latestVersion, input.currentVersion);
|
|
3170
|
+
if (choice === "interrupt") {
|
|
3171
|
+
process.exit(130);
|
|
3172
|
+
}
|
|
3173
|
+
if (choice !== "install") {
|
|
3174
|
+
return;
|
|
3175
|
+
}
|
|
3176
|
+
const installed = await installLatestVersion(input.packageName);
|
|
3177
|
+
if (installed) {
|
|
3178
|
+
stderr.write(
|
|
3179
|
+
"CodeSentinel updated to latest version. Rerun your command to use the new version.\n"
|
|
3180
|
+
);
|
|
3181
|
+
process.exit(0);
|
|
3182
|
+
} else {
|
|
3183
|
+
stderr.write(
|
|
3184
|
+
"CodeSentinel update failed. You can retry with: npm install -g @getcodesentinel/codesentinel@latest\n"
|
|
3185
|
+
);
|
|
3186
|
+
}
|
|
3187
|
+
} catch {
|
|
3188
|
+
}
|
|
3189
|
+
};
|
|
3190
|
+
|
|
2860
3191
|
// src/application/run-analyze-command.ts
|
|
2861
3192
|
import { resolve as resolve3 } from "path";
|
|
2862
3193
|
|
|
@@ -4098,6 +4429,29 @@ var computeDependencySignalScore = (ownSignals, inheritedSignals, inheritedSigna
|
|
|
4098
4429
|
return toUnitInterval(weightedTotal / maxWeightedTotal);
|
|
4099
4430
|
};
|
|
4100
4431
|
var clampConfidence = (value) => round45(toUnitInterval(value));
|
|
4432
|
+
var computeExternalMetadataConfidence = (external) => {
|
|
4433
|
+
if (!external.available) {
|
|
4434
|
+
return 0;
|
|
4435
|
+
}
|
|
4436
|
+
return round45(toUnitInterval(0.35 + external.metrics.metadataCoverage * 0.65));
|
|
4437
|
+
};
|
|
4438
|
+
var computeEvolutionHistoryConfidence = (structural, evolution, evolutionByFile) => {
|
|
4439
|
+
if (!evolution.available) {
|
|
4440
|
+
return 0;
|
|
4441
|
+
}
|
|
4442
|
+
const totalFiles = structural.files.length;
|
|
4443
|
+
if (totalFiles === 0) {
|
|
4444
|
+
return 1;
|
|
4445
|
+
}
|
|
4446
|
+
let coveredFiles = 0;
|
|
4447
|
+
for (const file of structural.files) {
|
|
4448
|
+
if (evolutionByFile.has(normalizePath2(file.id))) {
|
|
4449
|
+
coveredFiles += 1;
|
|
4450
|
+
}
|
|
4451
|
+
}
|
|
4452
|
+
const coverage = coveredFiles / totalFiles;
|
|
4453
|
+
return round45(toUnitInterval(0.3 + coverage * 0.7));
|
|
4454
|
+
};
|
|
4101
4455
|
var buildFactorTraces = (totalScore, inputs) => {
|
|
4102
4456
|
const positiveInputs = inputs.filter((input) => input.strength > 0);
|
|
4103
4457
|
const strengthTotal = positiveInputs.reduce((sum, input) => sum + input.strength, 0);
|
|
@@ -4198,6 +4552,7 @@ var computeDependencyScores = (external, config) => {
|
|
|
4198
4552
|
config.quantileClamp.upper
|
|
4199
4553
|
);
|
|
4200
4554
|
const dependencyContexts = /* @__PURE__ */ new Map();
|
|
4555
|
+
const metadataConfidence = computeExternalMetadataConfidence(external);
|
|
4201
4556
|
const dependencyScores = external.dependencies.map((dependency) => {
|
|
4202
4557
|
const signalScore = computeDependencySignalScore(
|
|
4203
4558
|
dependency.ownRiskSignals,
|
|
@@ -4232,7 +4587,7 @@ var computeDependencyScores = (external, config) => {
|
|
|
4232
4587
|
dependency.busFactor,
|
|
4233
4588
|
dependency.weeklyDownloads
|
|
4234
4589
|
].filter((value) => value !== null).length;
|
|
4235
|
-
const confidence = toUnitInterval(0.5 + availableMetricCount * 0.125);
|
|
4590
|
+
const confidence = toUnitInterval((0.5 + availableMetricCount * 0.125) * metadataConfidence);
|
|
4236
4591
|
dependencyContexts.set(dependency.name, {
|
|
4237
4592
|
signalScore: round45(signalScore),
|
|
4238
4593
|
stalenessRisk: round45(stalenessRisk),
|
|
@@ -4431,7 +4786,13 @@ var buildFragileClusters = (structural, evolution, fileScoresByFile, config) =>
|
|
|
4431
4786
|
var computeRiskSummary = (structural, evolution, external, config, traceCollector) => {
|
|
4432
4787
|
const collector = traceCollector;
|
|
4433
4788
|
const dependencyComputation = computeDependencyScores(external, config);
|
|
4789
|
+
const externalMetadataConfidence = computeExternalMetadataConfidence(external);
|
|
4434
4790
|
const evolutionByFile = mapEvolutionByFile(evolution);
|
|
4791
|
+
const evolutionHistoryConfidence = computeEvolutionHistoryConfidence(
|
|
4792
|
+
structural,
|
|
4793
|
+
evolution,
|
|
4794
|
+
evolutionByFile
|
|
4795
|
+
);
|
|
4435
4796
|
const evolutionScales = computeEvolutionScales(evolutionByFile, config);
|
|
4436
4797
|
const cycleFileSet = new Set(
|
|
4437
4798
|
structural.cycles.flatMap((cycle) => cycle.nodes.map((node) => normalizePath2(node)))
|
|
@@ -4615,7 +4976,7 @@ var computeRiskSummary = (structural, evolution, external, config, traceCollecto
|
|
|
4615
4976
|
weight: dimensionWeights.evolution,
|
|
4616
4977
|
amplification: null,
|
|
4617
4978
|
evidence: [{ kind: "file_metric", target: context.file, metric: "commitCount" }],
|
|
4618
|
-
confidence: evolution.available ? 1 : 0
|
|
4979
|
+
confidence: evolution.available ? evolutionHistoryConfidence * (context.rawMetrics.commitCount === null ? 0.5 : 1) : 0
|
|
4619
4980
|
},
|
|
4620
4981
|
{
|
|
4621
4982
|
factorId: "file.external",
|
|
@@ -4631,7 +4992,7 @@ var computeRiskSummary = (structural, evolution, external, config, traceCollecto
|
|
|
4631
4992
|
weight: dimensionWeights.external,
|
|
4632
4993
|
amplification: null,
|
|
4633
4994
|
evidence: [{ kind: "repository_metric", metric: "repositoryExternalPressure" }],
|
|
4634
|
-
confidence: external.available ? 0.7 : 0
|
|
4995
|
+
confidence: external.available ? 0.7 * externalMetadataConfidence : 0
|
|
4635
4996
|
},
|
|
4636
4997
|
{
|
|
4637
4998
|
factorId: "file.composite.interactions",
|
|
@@ -4759,7 +5120,7 @@ var computeRiskSummary = (structural, evolution, external, config, traceCollecto
|
|
|
4759
5120
|
weight: config.dependencyFactorWeights.signals,
|
|
4760
5121
|
amplification: config.dependencySignals.inheritedSignalMultiplier,
|
|
4761
5122
|
evidence: [{ kind: "dependency_metric", target: dependency.name, metric: "riskSignals" }],
|
|
4762
|
-
confidence: 0.95
|
|
5123
|
+
confidence: 0.95 * externalMetadataConfidence
|
|
4763
5124
|
},
|
|
4764
5125
|
{
|
|
4765
5126
|
factorId: "dependency.staleness",
|
|
@@ -4772,7 +5133,7 @@ var computeRiskSummary = (structural, evolution, external, config, traceCollecto
|
|
|
4772
5133
|
evidence: [
|
|
4773
5134
|
{ kind: "dependency_metric", target: dependency.name, metric: "daysSinceLastRelease" }
|
|
4774
5135
|
],
|
|
4775
|
-
confidence: hasMetadata ? 0.9 : 0.5
|
|
5136
|
+
confidence: (hasMetadata ? 0.9 : 0.5) * externalMetadataConfidence
|
|
4776
5137
|
},
|
|
4777
5138
|
{
|
|
4778
5139
|
factorId: "dependency.maintainer_concentration",
|
|
@@ -4787,7 +5148,7 @@ var computeRiskSummary = (structural, evolution, external, config, traceCollecto
|
|
|
4787
5148
|
evidence: [
|
|
4788
5149
|
{ kind: "dependency_metric", target: dependency.name, metric: "maintainerCount" }
|
|
4789
5150
|
],
|
|
4790
|
-
confidence: hasMetadata ? 0.9 : 0.5
|
|
5151
|
+
confidence: (hasMetadata ? 0.9 : 0.5) * externalMetadataConfidence
|
|
4791
5152
|
},
|
|
4792
5153
|
{
|
|
4793
5154
|
factorId: "dependency.topology",
|
|
@@ -4808,7 +5169,7 @@ var computeRiskSummary = (structural, evolution, external, config, traceCollecto
|
|
|
4808
5169
|
evidence: [
|
|
4809
5170
|
{ kind: "dependency_metric", target: dependency.name, metric: "dependencyDepth" }
|
|
4810
5171
|
],
|
|
4811
|
-
confidence: 1
|
|
5172
|
+
confidence: 1 * externalMetadataConfidence
|
|
4812
5173
|
},
|
|
4813
5174
|
{
|
|
4814
5175
|
factorId: "dependency.bus_factor",
|
|
@@ -4819,7 +5180,7 @@ var computeRiskSummary = (structural, evolution, external, config, traceCollecto
|
|
|
4819
5180
|
weight: config.dependencyFactorWeights.busFactorRisk,
|
|
4820
5181
|
amplification: null,
|
|
4821
5182
|
evidence: [{ kind: "dependency_metric", target: dependency.name, metric: "busFactor" }],
|
|
4822
|
-
confidence: context.rawMetrics.busFactor === null ? 0.5 : 0.85
|
|
5183
|
+
confidence: (context.rawMetrics.busFactor === null ? 0.5 : 0.85) * externalMetadataConfidence
|
|
4823
5184
|
},
|
|
4824
5185
|
{
|
|
4825
5186
|
factorId: "dependency.popularity_dampening",
|
|
@@ -4832,7 +5193,7 @@ var computeRiskSummary = (structural, evolution, external, config, traceCollecto
|
|
|
4832
5193
|
evidence: [
|
|
4833
5194
|
{ kind: "dependency_metric", target: dependency.name, metric: "weeklyDownloads" }
|
|
4834
5195
|
],
|
|
4835
|
-
confidence: context.rawMetrics.weeklyDownloads === null ? 0.4 : 0.9
|
|
5196
|
+
confidence: (context.rawMetrics.weeklyDownloads === null ? 0.4 : 0.9) * externalMetadataConfidence
|
|
4836
5197
|
}
|
|
4837
5198
|
]);
|
|
4838
5199
|
collector.record(
|
|
@@ -4889,7 +5250,7 @@ var computeRiskSummary = (structural, evolution, external, config, traceCollecto
|
|
|
4889
5250
|
weight: dimensionWeights.evolution,
|
|
4890
5251
|
amplification: null,
|
|
4891
5252
|
evidence: [{ kind: "repository_metric", metric: "evolutionDimension" }],
|
|
4892
|
-
confidence: evolution.available ?
|
|
5253
|
+
confidence: evolution.available ? evolutionHistoryConfidence : 0
|
|
4893
5254
|
},
|
|
4894
5255
|
{
|
|
4895
5256
|
factorId: "repository.external",
|
|
@@ -4900,7 +5261,7 @@ var computeRiskSummary = (structural, evolution, external, config, traceCollecto
|
|
|
4900
5261
|
weight: dimensionWeights.external,
|
|
4901
5262
|
amplification: null,
|
|
4902
5263
|
evidence: [{ kind: "repository_metric", metric: "externalDimension" }],
|
|
4903
|
-
confidence: external.available ? 0.8 : 0
|
|
5264
|
+
confidence: external.available ? 0.8 * externalMetadataConfidence : 0
|
|
4904
5265
|
},
|
|
4905
5266
|
{
|
|
4906
5267
|
factorId: "repository.composite.interactions",
|
|
@@ -5236,7 +5597,7 @@ var runAnalyzeCommand = async (inputPath, authorIdentityMode, options = {}, logg
|
|
|
5236
5597
|
};
|
|
5237
5598
|
|
|
5238
5599
|
// src/application/run-check-command.ts
|
|
5239
|
-
import { readFile, writeFile } from "fs/promises";
|
|
5600
|
+
import { readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
|
|
5240
5601
|
|
|
5241
5602
|
// src/application/build-analysis-snapshot.ts
|
|
5242
5603
|
var buildAnalysisSnapshot = async (inputPath, authorIdentityMode, options, logger) => {
|
|
@@ -5301,7 +5662,7 @@ var runCheckCommand = async (inputPath, authorIdentityMode, options, logger = cr
|
|
|
5301
5662
|
let diff;
|
|
5302
5663
|
if (options.baselinePath !== void 0) {
|
|
5303
5664
|
logger.info(`loading baseline snapshot: ${options.baselinePath}`);
|
|
5304
|
-
const baselineRaw = await
|
|
5665
|
+
const baselineRaw = await readFile2(options.baselinePath, "utf8");
|
|
5305
5666
|
try {
|
|
5306
5667
|
baseline = parseSnapshot(baselineRaw);
|
|
5307
5668
|
} catch (error) {
|
|
@@ -5327,7 +5688,7 @@ var runCheckCommand = async (inputPath, authorIdentityMode, options, logger = cr
|
|
|
5327
5688
|
options.outputFormat
|
|
5328
5689
|
);
|
|
5329
5690
|
if (options.outputPath !== void 0) {
|
|
5330
|
-
await
|
|
5691
|
+
await writeFile2(options.outputPath, rendered, "utf8");
|
|
5331
5692
|
logger.info(`check output written: ${options.outputPath}`);
|
|
5332
5693
|
}
|
|
5333
5694
|
return {
|
|
@@ -5340,7 +5701,7 @@ var runCheckCommand = async (inputPath, authorIdentityMode, options, logger = cr
|
|
|
5340
5701
|
};
|
|
5341
5702
|
|
|
5342
5703
|
// src/application/run-ci-command.ts
|
|
5343
|
-
import { readFile as
|
|
5704
|
+
import { readFile as readFile3, writeFile as writeFile3 } from "fs/promises";
|
|
5344
5705
|
import { relative as relative2, resolve as resolve4 } from "path";
|
|
5345
5706
|
var isPathOutsideBase = (value) => {
|
|
5346
5707
|
return value === ".." || value.startsWith("../") || value.startsWith("..\\");
|
|
@@ -5366,7 +5727,7 @@ var runCiCommand = async (inputPath, authorIdentityMode, options, logger = creat
|
|
|
5366
5727
|
logger
|
|
5367
5728
|
);
|
|
5368
5729
|
if (options.snapshotPath !== void 0) {
|
|
5369
|
-
await
|
|
5730
|
+
await writeFile3(options.snapshotPath, JSON.stringify(current, null, 2), "utf8");
|
|
5370
5731
|
logger.info(`snapshot written: ${options.snapshotPath}`);
|
|
5371
5732
|
}
|
|
5372
5733
|
let baseline;
|
|
@@ -5438,7 +5799,7 @@ var runCiCommand = async (inputPath, authorIdentityMode, options, logger = creat
|
|
|
5438
5799
|
diff = compareSnapshots(current, baseline);
|
|
5439
5800
|
} else if (options.baselinePath !== void 0) {
|
|
5440
5801
|
logger.info(`loading baseline snapshot: ${options.baselinePath}`);
|
|
5441
|
-
const baselineRaw = await
|
|
5802
|
+
const baselineRaw = await readFile3(options.baselinePath, "utf8");
|
|
5442
5803
|
try {
|
|
5443
5804
|
baseline = parseSnapshot(baselineRaw);
|
|
5444
5805
|
} catch (error) {
|
|
@@ -5460,7 +5821,7 @@ var runCiCommand = async (inputPath, authorIdentityMode, options, logger = creat
|
|
|
5460
5821
|
|
|
5461
5822
|
${ciMarkdown}`;
|
|
5462
5823
|
if (options.reportPath !== void 0) {
|
|
5463
|
-
await
|
|
5824
|
+
await writeFile3(options.reportPath, markdownSummary, "utf8");
|
|
5464
5825
|
logger.info(`report written: ${options.reportPath}`);
|
|
5465
5826
|
}
|
|
5466
5827
|
const machineReadable = {
|
|
@@ -5472,7 +5833,7 @@ ${ciMarkdown}`;
|
|
|
5472
5833
|
exitCode: gateResult.exitCode
|
|
5473
5834
|
};
|
|
5474
5835
|
if (options.jsonOutputPath !== void 0) {
|
|
5475
|
-
await
|
|
5836
|
+
await writeFile3(options.jsonOutputPath, JSON.stringify(machineReadable, null, 2), "utf8");
|
|
5476
5837
|
logger.info(`ci machine output written: ${options.jsonOutputPath}`);
|
|
5477
5838
|
}
|
|
5478
5839
|
return {
|
|
@@ -5486,7 +5847,7 @@ ${ciMarkdown}`;
|
|
|
5486
5847
|
};
|
|
5487
5848
|
|
|
5488
5849
|
// src/application/run-report-command.ts
|
|
5489
|
-
import { readFile as
|
|
5850
|
+
import { readFile as readFile4, writeFile as writeFile4 } from "fs/promises";
|
|
5490
5851
|
var runReportCommand = async (inputPath, authorIdentityMode, options, logger = createSilentLogger()) => {
|
|
5491
5852
|
logger.info("building analysis snapshot");
|
|
5492
5853
|
const current = await buildAnalysisSnapshot(
|
|
@@ -5499,7 +5860,7 @@ var runReportCommand = async (inputPath, authorIdentityMode, options, logger = c
|
|
|
5499
5860
|
logger
|
|
5500
5861
|
);
|
|
5501
5862
|
if (options.snapshotPath !== void 0) {
|
|
5502
|
-
await
|
|
5863
|
+
await writeFile4(options.snapshotPath, JSON.stringify(current, null, 2), "utf8");
|
|
5503
5864
|
logger.info(`snapshot written: ${options.snapshotPath}`);
|
|
5504
5865
|
}
|
|
5505
5866
|
let report;
|
|
@@ -5507,14 +5868,14 @@ var runReportCommand = async (inputPath, authorIdentityMode, options, logger = c
|
|
|
5507
5868
|
report = createReport(current);
|
|
5508
5869
|
} else {
|
|
5509
5870
|
logger.info(`loading baseline snapshot: ${options.comparePath}`);
|
|
5510
|
-
const baselineRaw = await
|
|
5871
|
+
const baselineRaw = await readFile4(options.comparePath, "utf8");
|
|
5511
5872
|
const baseline = parseSnapshot(baselineRaw);
|
|
5512
5873
|
const diff = compareSnapshots(current, baseline);
|
|
5513
5874
|
report = createReport(current, diff);
|
|
5514
5875
|
}
|
|
5515
5876
|
const rendered = formatReport(report, options.format);
|
|
5516
5877
|
if (options.outputPath !== void 0) {
|
|
5517
|
-
await
|
|
5878
|
+
await writeFile4(options.outputPath, rendered, "utf8");
|
|
5518
5879
|
logger.info(`report written: ${options.outputPath}`);
|
|
5519
5880
|
}
|
|
5520
5881
|
return { report, rendered };
|
|
@@ -5568,7 +5929,7 @@ var runExplainCommand = async (inputPath, authorIdentityMode, options, logger =
|
|
|
5568
5929
|
|
|
5569
5930
|
// src/index.ts
|
|
5570
5931
|
var program = new Command();
|
|
5571
|
-
var packageJsonPath = resolve5(
|
|
5932
|
+
var packageJsonPath = resolve5(dirname2(fileURLToPath(import.meta.url)), "../package.json");
|
|
5572
5933
|
var { version } = JSON.parse(readFileSync2(packageJsonPath, "utf8"));
|
|
5573
5934
|
var parseRecentWindowDays = (value) => {
|
|
5574
5935
|
const parsed = Number.parseInt(value, 10);
|
|
@@ -5886,5 +6247,11 @@ if (argv.length <= 2) {
|
|
|
5886
6247
|
program.outputHelp();
|
|
5887
6248
|
process.exit(0);
|
|
5888
6249
|
}
|
|
6250
|
+
await checkForCliUpdates({
|
|
6251
|
+
packageName: "@getcodesentinel/codesentinel",
|
|
6252
|
+
currentVersion: version,
|
|
6253
|
+
argv: process.argv,
|
|
6254
|
+
env: process.env
|
|
6255
|
+
});
|
|
5889
6256
|
await program.parseAsync(argv);
|
|
5890
6257
|
//# sourceMappingURL=index.js.map
|