@getcodesentinel/codesentinel 1.12.0 → 1.13.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/README.md +11 -4
- package/dist/index.js +178 -49
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -94,7 +94,7 @@ CodeSentinel combines three signals into a single, explainable risk profile:
|
|
|
94
94
|
|
|
95
95
|
The CLI output now includes a deterministic `risk` block composed from those dimensions:
|
|
96
96
|
|
|
97
|
-
- `
|
|
97
|
+
- `riskScore` and `normalizedScore`
|
|
98
98
|
- ranked `hotspots`
|
|
99
99
|
- `fragileClusters` (structural cycles + change coupling components)
|
|
100
100
|
- `dependencyAmplificationZones`
|
|
@@ -178,6 +178,9 @@ codesentinel analyze . --author-identity likely_merge
|
|
|
178
178
|
# Deterministic: strict email identity, no heuristic merging
|
|
179
179
|
codesentinel analyze . --author-identity strict_email
|
|
180
180
|
|
|
181
|
+
# Personal-project profile (down-weights single-maintainer ownership penalties)
|
|
182
|
+
codesentinel analyze . --risk-profile personal
|
|
183
|
+
|
|
181
184
|
# Tune recency window (days) used for evolution volatility
|
|
182
185
|
codesentinel analyze . --recent-window-days 60
|
|
183
186
|
|
|
@@ -228,6 +231,10 @@ Notes:
|
|
|
228
231
|
- `--output summary` (default) prints a compact result for terminal use.
|
|
229
232
|
- `--output json` (or `--json`) prints the full analysis object.
|
|
230
233
|
- `--recent-window-days <days>` customizes the git recency window used to compute `recentVolatility` (default: `30`).
|
|
234
|
+
- `--risk-profile default|personal` selects scoring profile.
|
|
235
|
+
- `default`: balanced team-oriented defaults.
|
|
236
|
+
- `personal`: lowers ownership concentration and bus-factor penalties for solo-maintainer repos.
|
|
237
|
+
- `personal` does not remove structural, churn, volatility, external, or interaction risk; scores can still be elevated when those signals are high.
|
|
231
238
|
|
|
232
239
|
When running through pnpm, pass CLI arguments after `--`:
|
|
233
240
|
|
|
@@ -355,7 +362,7 @@ Minimal shape:
|
|
|
355
362
|
"evolution": { "...": "..." },
|
|
356
363
|
"external": { "...": "..." },
|
|
357
364
|
"risk": {
|
|
358
|
-
"
|
|
365
|
+
"riskScore": 0,
|
|
359
366
|
"normalizedScore": 0,
|
|
360
367
|
"hotspots": [],
|
|
361
368
|
"fragileClusters": [],
|
|
@@ -366,7 +373,7 @@ Minimal shape:
|
|
|
366
373
|
|
|
367
374
|
How to read `risk` first:
|
|
368
375
|
|
|
369
|
-
- `
|
|
376
|
+
- `riskScore`: overall repository fragility index (`0..100`).
|
|
370
377
|
- `hotspots`: ranked files to inspect first.
|
|
371
378
|
- `fragileClusters`: groups of files with structural-cycle or co-change fragility.
|
|
372
379
|
- `dependencyAmplificationZones`: files where external dependency pressure intersects with local fragility.
|
|
@@ -391,7 +398,7 @@ These ranges are heuristics for triage, not incident probability.
|
|
|
391
398
|
|
|
392
399
|
### What Moves Scores
|
|
393
400
|
|
|
394
|
-
`risk.
|
|
401
|
+
`risk.riskScore` and `risk.fileScores[*].score` increase when:
|
|
395
402
|
|
|
396
403
|
- structurally central files/modules change frequently,
|
|
397
404
|
- ownership is highly concentrated in volatile files,
|
package/dist/index.js
CHANGED
|
@@ -1524,9 +1524,7 @@ var compareSnapshots = (current, baseline) => {
|
|
|
1524
1524
|
const hotspots = diffSets(currentHotspots, baselineHotspots);
|
|
1525
1525
|
const cycles = diffSets(currentCycles, baselineCycles);
|
|
1526
1526
|
return {
|
|
1527
|
-
|
|
1528
|
-
current.analysis.risk.repositoryScore - baseline.analysis.risk.repositoryScore
|
|
1529
|
-
),
|
|
1527
|
+
riskScoreDelta: round43(current.analysis.risk.riskScore - baseline.analysis.risk.riskScore),
|
|
1530
1528
|
normalizedScoreDelta: round43(
|
|
1531
1529
|
current.analysis.risk.normalizedScore - baseline.analysis.risk.normalizedScore
|
|
1532
1530
|
),
|
|
@@ -1652,9 +1650,9 @@ var createReport = (snapshot, diff) => {
|
|
|
1652
1650
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1653
1651
|
repository: {
|
|
1654
1652
|
targetPath: snapshot.analysis.structural.targetPath,
|
|
1655
|
-
|
|
1653
|
+
riskScore: snapshot.analysis.risk.riskScore,
|
|
1656
1654
|
normalizedScore: snapshot.analysis.risk.normalizedScore,
|
|
1657
|
-
riskTier: toRiskTier(snapshot.analysis.risk.
|
|
1655
|
+
riskTier: toRiskTier(snapshot.analysis.risk.riskScore),
|
|
1658
1656
|
confidence: repositoryConfidence(snapshot),
|
|
1659
1657
|
dimensionScores: repositoryDimensionScores(snapshot)
|
|
1660
1658
|
},
|
|
@@ -1706,7 +1704,7 @@ var renderTextDiff = (report) => {
|
|
|
1706
1704
|
return [
|
|
1707
1705
|
"",
|
|
1708
1706
|
"Diff",
|
|
1709
|
-
`
|
|
1707
|
+
` riskScoreDelta: ${report.diff.riskScoreDelta}`,
|
|
1710
1708
|
` normalizedScoreDelta: ${report.diff.normalizedScoreDelta}`,
|
|
1711
1709
|
` newHotspots: ${report.diff.newHotspots.join(", ") || "none"}`,
|
|
1712
1710
|
` resolvedHotspots: ${report.diff.resolvedHotspots.join(", ") || "none"}`,
|
|
@@ -1718,7 +1716,7 @@ var renderTextReport = (report) => {
|
|
|
1718
1716
|
const lines = [];
|
|
1719
1717
|
lines.push("Repository Summary");
|
|
1720
1718
|
lines.push(` target: ${report.repository.targetPath}`);
|
|
1721
|
-
lines.push(`
|
|
1719
|
+
lines.push(` riskScore: ${report.repository.riskScore}`);
|
|
1722
1720
|
lines.push(` normalizedScore: ${report.repository.normalizedScore}`);
|
|
1723
1721
|
lines.push(` riskTier: ${report.repository.riskTier}`);
|
|
1724
1722
|
lines.push(` confidence: ${report.repository.confidence ?? "n/a"}`);
|
|
@@ -1780,7 +1778,7 @@ var renderMarkdownDiff = (report) => {
|
|
|
1780
1778
|
return [
|
|
1781
1779
|
"",
|
|
1782
1780
|
"## Diff",
|
|
1783
|
-
`-
|
|
1781
|
+
`- riskScoreDelta: \`${report.diff.riskScoreDelta}\``,
|
|
1784
1782
|
`- normalizedScoreDelta: \`${report.diff.normalizedScoreDelta}\``,
|
|
1785
1783
|
`- newHotspots: ${report.diff.newHotspots.map((item) => `\`${item}\``).join(", ") || "none"}`,
|
|
1786
1784
|
`- resolvedHotspots: ${report.diff.resolvedHotspots.map((item) => `\`${item}\``).join(", ") || "none"}`,
|
|
@@ -1794,7 +1792,7 @@ var renderMarkdownReport = (report) => {
|
|
|
1794
1792
|
lines.push("");
|
|
1795
1793
|
lines.push("## Repository Summary");
|
|
1796
1794
|
lines.push(`- target: \`${report.repository.targetPath}\``);
|
|
1797
|
-
lines.push(`-
|
|
1795
|
+
lines.push(`- riskScore: \`${report.repository.riskScore}\``);
|
|
1798
1796
|
lines.push(`- normalizedScore: \`${report.repository.normalizedScore}\``);
|
|
1799
1797
|
lines.push(`- riskTier: \`${report.repository.riskTier}\``);
|
|
1800
1798
|
lines.push(`- confidence: \`${report.repository.confidence ?? "n/a"}\``);
|
|
@@ -1973,7 +1971,7 @@ var evaluateGates = (input) => {
|
|
|
1973
1971
|
const evaluatedGates = [];
|
|
1974
1972
|
if (config.maxRepoScore !== void 0) {
|
|
1975
1973
|
evaluatedGates.push("max-repo-score");
|
|
1976
|
-
const current = input.current.analysis.risk.
|
|
1974
|
+
const current = input.current.analysis.risk.riskScore;
|
|
1977
1975
|
if (current > config.maxRepoScore) {
|
|
1978
1976
|
violations.push(
|
|
1979
1977
|
makeViolation(
|
|
@@ -1981,7 +1979,7 @@ var evaluateGates = (input) => {
|
|
|
1981
1979
|
"error",
|
|
1982
1980
|
`Repository score ${current} exceeds configured max ${config.maxRepoScore}.`,
|
|
1983
1981
|
[input.current.analysis.structural.targetPath],
|
|
1984
|
-
[{ kind: "repository_metric", metric: "
|
|
1982
|
+
[{ kind: "repository_metric", metric: "riskScore" }]
|
|
1985
1983
|
)
|
|
1986
1984
|
);
|
|
1987
1985
|
}
|
|
@@ -2093,7 +2091,7 @@ var renderCheckText = (snapshot, result) => {
|
|
|
2093
2091
|
const lines = [];
|
|
2094
2092
|
lines.push("CodeSentinel Check");
|
|
2095
2093
|
lines.push(`target: ${snapshot.analysis.structural.targetPath}`);
|
|
2096
|
-
lines.push(`
|
|
2094
|
+
lines.push(`riskScore: ${snapshot.analysis.risk.riskScore}`);
|
|
2097
2095
|
lines.push(`evaluatedGates: ${result.evaluatedGates.join(", ") || "none"}`);
|
|
2098
2096
|
lines.push(`violations: ${result.violations.length}`);
|
|
2099
2097
|
lines.push(`exitCode: ${result.exitCode}`);
|
|
@@ -2112,7 +2110,7 @@ var renderCheckMarkdown = (snapshot, result) => {
|
|
|
2112
2110
|
const lines = [];
|
|
2113
2111
|
lines.push("## CodeSentinel CI Summary");
|
|
2114
2112
|
lines.push(`- target: \`${snapshot.analysis.structural.targetPath}\``);
|
|
2115
|
-
lines.push(`-
|
|
2113
|
+
lines.push(`- riskScore: \`${snapshot.analysis.risk.riskScore}\``);
|
|
2116
2114
|
lines.push(
|
|
2117
2115
|
`- evaluatedGates: ${result.evaluatedGates.map((item) => `\`${item}\``).join(", ") || "none"}`
|
|
2118
2116
|
);
|
|
@@ -2495,7 +2493,7 @@ var createSummaryShape = (summary) => ({
|
|
|
2495
2493
|
reason: summary.external.reason
|
|
2496
2494
|
},
|
|
2497
2495
|
risk: {
|
|
2498
|
-
|
|
2496
|
+
riskScore: summary.risk.riskScore,
|
|
2499
2497
|
normalizedScore: summary.risk.normalizedScore,
|
|
2500
2498
|
hotspotsTop: summary.risk.hotspots.slice(0, 5).map((hotspot) => ({
|
|
2501
2499
|
file: hotspot.file,
|
|
@@ -2560,7 +2558,7 @@ var formatFactorEvidence = (factor) => {
|
|
|
2560
2558
|
return `structural\xD7evolution=${formatNumber(factor.rawMetrics["structuralEvolution"])}, central instability=${formatNumber(factor.rawMetrics["centralInstability"])}, dependency amplification=${formatNumber(factor.rawMetrics["dependencyAmplification"])}`;
|
|
2561
2559
|
}
|
|
2562
2560
|
if (factor.factorId === "file.structural") {
|
|
2563
|
-
return `fanIn=${formatNumber(factor.rawMetrics["fanIn"])}, fanOut=${formatNumber(factor.rawMetrics["fanOut"])}, depth=${formatNumber(factor.rawMetrics["depth"])}, inCycle=${formatNumber(factor.rawMetrics["cycleParticipation"])}`;
|
|
2561
|
+
return `fanIn=${formatNumber(factor.rawMetrics["fanIn"])}, fanOut=${formatNumber(factor.rawMetrics["fanOut"])}, depth=${formatNumber(factor.rawMetrics["depth"])}, inCycle=${formatNumber(factor.rawMetrics["cycleParticipation"])}, structuralAttenuation=${formatNumber(factor.rawMetrics["structuralAttenuation"])}`;
|
|
2564
2562
|
}
|
|
2565
2563
|
if (factor.factorId === "file.evolution") {
|
|
2566
2564
|
return `commitCount=${formatNumber(factor.rawMetrics["commitCount"])}, churnTotal=${formatNumber(factor.rawMetrics["churnTotal"])}, recentVolatility=${formatNumber(factor.rawMetrics["recentVolatility"])}`;
|
|
@@ -2667,8 +2665,8 @@ var renderText = (payload) => {
|
|
|
2667
2665
|
const dimensionScores = repositoryDimensionScores2(repositoryTarget);
|
|
2668
2666
|
const compositeFactors = repositoryTopFactors.filter((factor) => factor.family === "composite");
|
|
2669
2667
|
lines.push(`target: ${payload.summary.structural.targetPath}`);
|
|
2670
|
-
lines.push(`
|
|
2671
|
-
lines.push(`riskBand: ${toRiskBand(payload.summary.risk.
|
|
2668
|
+
lines.push(`riskScore: ${payload.summary.risk.riskScore}`);
|
|
2669
|
+
lines.push(`riskBand: ${toRiskBand(payload.summary.risk.riskScore)}`);
|
|
2672
2670
|
lines.push(`selectedTargets: ${payload.selectedTargets.length}`);
|
|
2673
2671
|
lines.push("dimensionScores:");
|
|
2674
2672
|
lines.push(` structural: ${formatDimension(dimensionScores.structural)}`);
|
|
@@ -2707,8 +2705,8 @@ var renderMarkdown = (payload) => {
|
|
|
2707
2705
|
const compositeFactors = repositoryTopFactors.filter((factor) => factor.family === "composite");
|
|
2708
2706
|
lines.push(`# CodeSentinel Explanation`);
|
|
2709
2707
|
lines.push(`- target: \`${payload.summary.structural.targetPath}\``);
|
|
2710
|
-
lines.push(`-
|
|
2711
|
-
lines.push(`- riskBand: \`${toRiskBand(payload.summary.risk.
|
|
2708
|
+
lines.push(`- riskScore: \`${payload.summary.risk.riskScore}\``);
|
|
2709
|
+
lines.push(`- riskBand: \`${toRiskBand(payload.summary.risk.riskScore)}\``);
|
|
2712
2710
|
lines.push(`- selectedTargets: \`${payload.selectedTargets.length}\``);
|
|
2713
2711
|
lines.push("");
|
|
2714
2712
|
lines.push("## Dimension Scores (0-100)");
|
|
@@ -4308,6 +4306,17 @@ var DEFAULT_RISK_ENGINE_CONFIG = {
|
|
|
4308
4306
|
externalDimension: {
|
|
4309
4307
|
topDependencyPercentile: 0.85,
|
|
4310
4308
|
dependencyDepthHalfLife: 6
|
|
4309
|
+
},
|
|
4310
|
+
// Reduce false positives for thin aggregation hubs (for example, barrel/index re-export files)
|
|
4311
|
+
// that are structurally central but have low churn density and no cycle participation.
|
|
4312
|
+
aggregatorAttenuation: {
|
|
4313
|
+
enabled: true,
|
|
4314
|
+
minFanIn: 6,
|
|
4315
|
+
minFanOut: 4,
|
|
4316
|
+
minCommitCount: 4,
|
|
4317
|
+
maxChurnPerCommit: 24,
|
|
4318
|
+
maxChurnPerDependency: 10,
|
|
4319
|
+
maxStructuralReduction: 0.3
|
|
4311
4320
|
}
|
|
4312
4321
|
};
|
|
4313
4322
|
var toUnitInterval = (value) => Number.isFinite(value) ? Math.min(1, Math.max(0, value)) : 0;
|
|
@@ -4400,6 +4409,35 @@ var normalizeWithScale = (value, scale) => {
|
|
|
4400
4409
|
return toUnitInterval((value - scale.lower) / (scale.upper - scale.lower));
|
|
4401
4410
|
};
|
|
4402
4411
|
var normalizePath2 = (path) => path.replaceAll("\\", "/");
|
|
4412
|
+
var computeAggregatorAttenuation = (input) => {
|
|
4413
|
+
const { fanIn, fanOut, inCycle, evolutionMetrics, config } = input;
|
|
4414
|
+
if (!config.enabled || inCycle > 0) {
|
|
4415
|
+
return 1;
|
|
4416
|
+
}
|
|
4417
|
+
if (fanIn < config.minFanIn || fanOut < config.minFanOut) {
|
|
4418
|
+
return 1;
|
|
4419
|
+
}
|
|
4420
|
+
if (evolutionMetrics === void 0 || evolutionMetrics.commitCount < config.minCommitCount) {
|
|
4421
|
+
return 1;
|
|
4422
|
+
}
|
|
4423
|
+
const churnPerCommit = evolutionMetrics.churnTotal / Math.max(1, evolutionMetrics.commitCount);
|
|
4424
|
+
const churnPerDependency = evolutionMetrics.churnTotal / Math.max(1, fanOut);
|
|
4425
|
+
if (churnPerCommit > config.maxChurnPerCommit || churnPerDependency > config.maxChurnPerDependency) {
|
|
4426
|
+
return 1;
|
|
4427
|
+
}
|
|
4428
|
+
const fanInSignal = toUnitInterval((fanIn - config.minFanIn) / Math.max(1, config.minFanIn));
|
|
4429
|
+
const fanOutSignal = toUnitInterval((fanOut - config.minFanOut) / Math.max(1, config.minFanOut));
|
|
4430
|
+
const lowChurnPerCommitSignal = 1 - toUnitInterval(churnPerCommit / config.maxChurnPerCommit);
|
|
4431
|
+
const lowChurnPerDependencySignal = 1 - toUnitInterval(churnPerDependency / config.maxChurnPerDependency);
|
|
4432
|
+
const attenuationConfidence = average([
|
|
4433
|
+
fanInSignal,
|
|
4434
|
+
fanOutSignal,
|
|
4435
|
+
lowChurnPerCommitSignal,
|
|
4436
|
+
lowChurnPerDependencySignal
|
|
4437
|
+
]);
|
|
4438
|
+
const reduction = toUnitInterval(config.maxStructuralReduction) * attenuationConfidence;
|
|
4439
|
+
return round45(toUnitInterval(1 - reduction));
|
|
4440
|
+
};
|
|
4403
4441
|
var dependencySignalWeights = {
|
|
4404
4442
|
single_maintainer: 0.3,
|
|
4405
4443
|
abandoned: 0.3,
|
|
@@ -4429,6 +4467,29 @@ var computeDependencySignalScore = (ownSignals, inheritedSignals, inheritedSigna
|
|
|
4429
4467
|
return toUnitInterval(weightedTotal / maxWeightedTotal);
|
|
4430
4468
|
};
|
|
4431
4469
|
var clampConfidence = (value) => round45(toUnitInterval(value));
|
|
4470
|
+
var computeExternalMetadataConfidence = (external) => {
|
|
4471
|
+
if (!external.available) {
|
|
4472
|
+
return 0;
|
|
4473
|
+
}
|
|
4474
|
+
return round45(toUnitInterval(0.35 + external.metrics.metadataCoverage * 0.65));
|
|
4475
|
+
};
|
|
4476
|
+
var computeEvolutionHistoryConfidence = (structural, evolution, evolutionByFile) => {
|
|
4477
|
+
if (!evolution.available) {
|
|
4478
|
+
return 0;
|
|
4479
|
+
}
|
|
4480
|
+
const totalFiles = structural.files.length;
|
|
4481
|
+
if (totalFiles === 0) {
|
|
4482
|
+
return 1;
|
|
4483
|
+
}
|
|
4484
|
+
let coveredFiles = 0;
|
|
4485
|
+
for (const file of structural.files) {
|
|
4486
|
+
if (evolutionByFile.has(normalizePath2(file.id))) {
|
|
4487
|
+
coveredFiles += 1;
|
|
4488
|
+
}
|
|
4489
|
+
}
|
|
4490
|
+
const coverage = coveredFiles / totalFiles;
|
|
4491
|
+
return round45(toUnitInterval(0.3 + coverage * 0.7));
|
|
4492
|
+
};
|
|
4432
4493
|
var buildFactorTraces = (totalScore, inputs) => {
|
|
4433
4494
|
const positiveInputs = inputs.filter((input) => input.strength > 0);
|
|
4434
4495
|
const strengthTotal = positiveInputs.reduce((sum, input) => sum + input.strength, 0);
|
|
@@ -4529,6 +4590,7 @@ var computeDependencyScores = (external, config) => {
|
|
|
4529
4590
|
config.quantileClamp.upper
|
|
4530
4591
|
);
|
|
4531
4592
|
const dependencyContexts = /* @__PURE__ */ new Map();
|
|
4593
|
+
const metadataConfidence = computeExternalMetadataConfidence(external);
|
|
4532
4594
|
const dependencyScores = external.dependencies.map((dependency) => {
|
|
4533
4595
|
const signalScore = computeDependencySignalScore(
|
|
4534
4596
|
dependency.ownRiskSignals,
|
|
@@ -4563,7 +4625,7 @@ var computeDependencyScores = (external, config) => {
|
|
|
4563
4625
|
dependency.busFactor,
|
|
4564
4626
|
dependency.weeklyDownloads
|
|
4565
4627
|
].filter((value) => value !== null).length;
|
|
4566
|
-
const confidence = toUnitInterval(0.5 + availableMetricCount * 0.125);
|
|
4628
|
+
const confidence = toUnitInterval((0.5 + availableMetricCount * 0.125) * metadataConfidence);
|
|
4567
4629
|
dependencyContexts.set(dependency.name, {
|
|
4568
4630
|
signalScore: round45(signalScore),
|
|
4569
4631
|
stalenessRisk: round45(stalenessRisk),
|
|
@@ -4762,7 +4824,13 @@ var buildFragileClusters = (structural, evolution, fileScoresByFile, config) =>
|
|
|
4762
4824
|
var computeRiskSummary = (structural, evolution, external, config, traceCollector) => {
|
|
4763
4825
|
const collector = traceCollector;
|
|
4764
4826
|
const dependencyComputation = computeDependencyScores(external, config);
|
|
4827
|
+
const externalMetadataConfidence = computeExternalMetadataConfidence(external);
|
|
4765
4828
|
const evolutionByFile = mapEvolutionByFile(evolution);
|
|
4829
|
+
const evolutionHistoryConfidence = computeEvolutionHistoryConfidence(
|
|
4830
|
+
structural,
|
|
4831
|
+
evolution,
|
|
4832
|
+
evolutionByFile
|
|
4833
|
+
);
|
|
4766
4834
|
const evolutionScales = computeEvolutionScales(evolutionByFile, config);
|
|
4767
4835
|
const cycleFileSet = new Set(
|
|
4768
4836
|
structural.cycles.flatMap((cycle) => cycle.nodes.map((node) => normalizePath2(node)))
|
|
@@ -4794,10 +4862,10 @@ var computeRiskSummary = (structural, evolution, external, config, traceCollecto
|
|
|
4794
4862
|
const fanOutRisk = normalizeWithScale(logScale(file.fanOut), fanOutScale);
|
|
4795
4863
|
const depthRisk = normalizeWithScale(file.depth, depthScale);
|
|
4796
4864
|
const structuralWeights = config.structuralFactorWeights;
|
|
4797
|
-
const
|
|
4865
|
+
const structuralFactorRaw = toUnitInterval(
|
|
4798
4866
|
fanInRisk * structuralWeights.fanIn + fanOutRisk * structuralWeights.fanOut + depthRisk * structuralWeights.depth + inCycle * structuralWeights.cycleParticipation
|
|
4799
4867
|
);
|
|
4800
|
-
const
|
|
4868
|
+
const structuralCentralityRaw = toUnitInterval((fanInRisk + fanOutRisk) / 2);
|
|
4801
4869
|
let evolutionFactor = 0;
|
|
4802
4870
|
let frequencyRisk = 0;
|
|
4803
4871
|
let churnRisk = 0;
|
|
@@ -4824,6 +4892,15 @@ var computeRiskSummary = (structural, evolution, external, config, traceCollecto
|
|
|
4824
4892
|
frequencyRisk * evolutionWeights.frequency + churnRisk * evolutionWeights.churn + volatilityRisk * evolutionWeights.recentVolatility + ownershipConcentrationRisk * evolutionWeights.ownershipConcentration + busFactorRisk * evolutionWeights.busFactorRisk
|
|
4825
4893
|
);
|
|
4826
4894
|
}
|
|
4895
|
+
const structuralAttenuation = computeAggregatorAttenuation({
|
|
4896
|
+
fanIn: file.fanIn,
|
|
4897
|
+
fanOut: file.fanOut,
|
|
4898
|
+
inCycle,
|
|
4899
|
+
evolutionMetrics,
|
|
4900
|
+
config: config.aggregatorAttenuation
|
|
4901
|
+
});
|
|
4902
|
+
const structuralFactor = toUnitInterval(structuralFactorRaw * structuralAttenuation);
|
|
4903
|
+
const structuralCentrality = toUnitInterval(structuralCentralityRaw * structuralAttenuation);
|
|
4827
4904
|
const dependencyAffinity = toUnitInterval(structuralCentrality * 0.6 + evolutionFactor * 0.4);
|
|
4828
4905
|
const externalFactor = external.available ? toUnitInterval(dependencyComputation.repositoryExternalPressure * dependencyAffinity) : 0;
|
|
4829
4906
|
const structuralBase = structuralFactor * dimensionWeights.structural;
|
|
@@ -4868,7 +4945,8 @@ var computeRiskSummary = (structural, evolution, external, config, traceCollecto
|
|
|
4868
4945
|
topAuthorShare: evolutionMetrics?.topAuthorShare ?? null,
|
|
4869
4946
|
busFactor: evolutionMetrics?.busFactor ?? null,
|
|
4870
4947
|
dependencyAffinity: round45(dependencyAffinity),
|
|
4871
|
-
repositoryExternalPressure: round45(dependencyComputation.repositoryExternalPressure)
|
|
4948
|
+
repositoryExternalPressure: round45(dependencyComputation.repositoryExternalPressure),
|
|
4949
|
+
structuralAttenuation: round45(structuralAttenuation)
|
|
4872
4950
|
},
|
|
4873
4951
|
normalizedMetrics: {
|
|
4874
4952
|
fanInRisk: round45(fanInRisk),
|
|
@@ -4911,7 +4989,8 @@ var computeRiskSummary = (structural, evolution, external, config, traceCollecto
|
|
|
4911
4989
|
fanIn: context.rawMetrics.fanIn,
|
|
4912
4990
|
fanOut: context.rawMetrics.fanOut,
|
|
4913
4991
|
depth: context.rawMetrics.depth,
|
|
4914
|
-
cycleParticipation: context.rawMetrics.cycleParticipation
|
|
4992
|
+
cycleParticipation: context.rawMetrics.cycleParticipation,
|
|
4993
|
+
structuralAttenuation: context.rawMetrics.structuralAttenuation
|
|
4915
4994
|
},
|
|
4916
4995
|
normalizedMetrics: {
|
|
4917
4996
|
fanInRisk: context.normalizedMetrics.fanInRisk,
|
|
@@ -4946,7 +5025,7 @@ var computeRiskSummary = (structural, evolution, external, config, traceCollecto
|
|
|
4946
5025
|
weight: dimensionWeights.evolution,
|
|
4947
5026
|
amplification: null,
|
|
4948
5027
|
evidence: [{ kind: "file_metric", target: context.file, metric: "commitCount" }],
|
|
4949
|
-
confidence: evolution.available ? 1 : 0
|
|
5028
|
+
confidence: evolution.available ? evolutionHistoryConfidence * (context.rawMetrics.commitCount === null ? 0.5 : 1) : 0
|
|
4950
5029
|
},
|
|
4951
5030
|
{
|
|
4952
5031
|
factorId: "file.external",
|
|
@@ -4962,7 +5041,7 @@ var computeRiskSummary = (structural, evolution, external, config, traceCollecto
|
|
|
4962
5041
|
weight: dimensionWeights.external,
|
|
4963
5042
|
amplification: null,
|
|
4964
5043
|
evidence: [{ kind: "repository_metric", metric: "repositoryExternalPressure" }],
|
|
4965
|
-
confidence: external.available ? 0.7 : 0
|
|
5044
|
+
confidence: external.available ? 0.7 * externalMetadataConfidence : 0
|
|
4966
5045
|
},
|
|
4967
5046
|
{
|
|
4968
5047
|
factorId: "file.composite.interactions",
|
|
@@ -5090,7 +5169,7 @@ var computeRiskSummary = (structural, evolution, external, config, traceCollecto
|
|
|
5090
5169
|
weight: config.dependencyFactorWeights.signals,
|
|
5091
5170
|
amplification: config.dependencySignals.inheritedSignalMultiplier,
|
|
5092
5171
|
evidence: [{ kind: "dependency_metric", target: dependency.name, metric: "riskSignals" }],
|
|
5093
|
-
confidence: 0.95
|
|
5172
|
+
confidence: 0.95 * externalMetadataConfidence
|
|
5094
5173
|
},
|
|
5095
5174
|
{
|
|
5096
5175
|
factorId: "dependency.staleness",
|
|
@@ -5103,7 +5182,7 @@ var computeRiskSummary = (structural, evolution, external, config, traceCollecto
|
|
|
5103
5182
|
evidence: [
|
|
5104
5183
|
{ kind: "dependency_metric", target: dependency.name, metric: "daysSinceLastRelease" }
|
|
5105
5184
|
],
|
|
5106
|
-
confidence: hasMetadata ? 0.9 : 0.5
|
|
5185
|
+
confidence: (hasMetadata ? 0.9 : 0.5) * externalMetadataConfidence
|
|
5107
5186
|
},
|
|
5108
5187
|
{
|
|
5109
5188
|
factorId: "dependency.maintainer_concentration",
|
|
@@ -5118,7 +5197,7 @@ var computeRiskSummary = (structural, evolution, external, config, traceCollecto
|
|
|
5118
5197
|
evidence: [
|
|
5119
5198
|
{ kind: "dependency_metric", target: dependency.name, metric: "maintainerCount" }
|
|
5120
5199
|
],
|
|
5121
|
-
confidence: hasMetadata ? 0.9 : 0.5
|
|
5200
|
+
confidence: (hasMetadata ? 0.9 : 0.5) * externalMetadataConfidence
|
|
5122
5201
|
},
|
|
5123
5202
|
{
|
|
5124
5203
|
factorId: "dependency.topology",
|
|
@@ -5139,7 +5218,7 @@ var computeRiskSummary = (structural, evolution, external, config, traceCollecto
|
|
|
5139
5218
|
evidence: [
|
|
5140
5219
|
{ kind: "dependency_metric", target: dependency.name, metric: "dependencyDepth" }
|
|
5141
5220
|
],
|
|
5142
|
-
confidence: 1
|
|
5221
|
+
confidence: 1 * externalMetadataConfidence
|
|
5143
5222
|
},
|
|
5144
5223
|
{
|
|
5145
5224
|
factorId: "dependency.bus_factor",
|
|
@@ -5150,7 +5229,7 @@ var computeRiskSummary = (structural, evolution, external, config, traceCollecto
|
|
|
5150
5229
|
weight: config.dependencyFactorWeights.busFactorRisk,
|
|
5151
5230
|
amplification: null,
|
|
5152
5231
|
evidence: [{ kind: "dependency_metric", target: dependency.name, metric: "busFactor" }],
|
|
5153
|
-
confidence: context.rawMetrics.busFactor === null ? 0.5 : 0.85
|
|
5232
|
+
confidence: (context.rawMetrics.busFactor === null ? 0.5 : 0.85) * externalMetadataConfidence
|
|
5154
5233
|
},
|
|
5155
5234
|
{
|
|
5156
5235
|
factorId: "dependency.popularity_dampening",
|
|
@@ -5163,7 +5242,7 @@ var computeRiskSummary = (structural, evolution, external, config, traceCollecto
|
|
|
5163
5242
|
evidence: [
|
|
5164
5243
|
{ kind: "dependency_metric", target: dependency.name, metric: "weeklyDownloads" }
|
|
5165
5244
|
],
|
|
5166
|
-
confidence: context.rawMetrics.weeklyDownloads === null ? 0.4 : 0.9
|
|
5245
|
+
confidence: (context.rawMetrics.weeklyDownloads === null ? 0.4 : 0.9) * externalMetadataConfidence
|
|
5167
5246
|
}
|
|
5168
5247
|
]);
|
|
5169
5248
|
collector.record(
|
|
@@ -5197,9 +5276,9 @@ var computeRiskSummary = (structural, evolution, external, config, traceCollecto
|
|
|
5197
5276
|
criticalInstability * config.interactionWeights.centralInstability,
|
|
5198
5277
|
dependencyAmplification * config.interactionWeights.dependencyAmplification
|
|
5199
5278
|
]);
|
|
5200
|
-
const
|
|
5279
|
+
const riskScore = round45(repositoryNormalizedScore * 100);
|
|
5201
5280
|
if (collector !== void 0) {
|
|
5202
|
-
const repositoryFactors = buildFactorTraces(
|
|
5281
|
+
const repositoryFactors = buildFactorTraces(riskScore, [
|
|
5203
5282
|
{
|
|
5204
5283
|
factorId: "repository.structural",
|
|
5205
5284
|
family: "structural",
|
|
@@ -5220,7 +5299,7 @@ var computeRiskSummary = (structural, evolution, external, config, traceCollecto
|
|
|
5220
5299
|
weight: dimensionWeights.evolution,
|
|
5221
5300
|
amplification: null,
|
|
5222
5301
|
evidence: [{ kind: "repository_metric", metric: "evolutionDimension" }],
|
|
5223
|
-
confidence: evolution.available ?
|
|
5302
|
+
confidence: evolution.available ? evolutionHistoryConfidence : 0
|
|
5224
5303
|
},
|
|
5225
5304
|
{
|
|
5226
5305
|
factorId: "repository.external",
|
|
@@ -5231,7 +5310,7 @@ var computeRiskSummary = (structural, evolution, external, config, traceCollecto
|
|
|
5231
5310
|
weight: dimensionWeights.external,
|
|
5232
5311
|
amplification: null,
|
|
5233
5312
|
evidence: [{ kind: "repository_metric", metric: "externalDimension" }],
|
|
5234
|
-
confidence: external.available ? 0.8 : 0
|
|
5313
|
+
confidence: external.available ? 0.8 * externalMetadataConfidence : 0
|
|
5235
5314
|
},
|
|
5236
5315
|
{
|
|
5237
5316
|
factorId: "repository.composite.interactions",
|
|
@@ -5262,14 +5341,14 @@ var computeRiskSummary = (structural, evolution, external, config, traceCollecto
|
|
|
5262
5341
|
buildTargetTrace(
|
|
5263
5342
|
"repository",
|
|
5264
5343
|
structural.targetPath,
|
|
5265
|
-
|
|
5344
|
+
riskScore,
|
|
5266
5345
|
repositoryNormalizedScore,
|
|
5267
5346
|
repositoryFactors
|
|
5268
5347
|
)
|
|
5269
5348
|
);
|
|
5270
5349
|
}
|
|
5271
5350
|
return {
|
|
5272
|
-
|
|
5351
|
+
riskScore,
|
|
5273
5352
|
normalizedScore: round45(repositoryNormalizedScore),
|
|
5274
5353
|
hotspots,
|
|
5275
5354
|
fragileClusters,
|
|
@@ -5360,6 +5439,10 @@ var mergeConfig = (overrides) => {
|
|
|
5360
5439
|
externalDimension: {
|
|
5361
5440
|
...DEFAULT_RISK_ENGINE_CONFIG.externalDimension,
|
|
5362
5441
|
...overrides.externalDimension
|
|
5442
|
+
},
|
|
5443
|
+
aggregatorAttenuation: {
|
|
5444
|
+
...DEFAULT_RISK_ENGINE_CONFIG.aggregatorAttenuation,
|
|
5445
|
+
...overrides.aggregatorAttenuation
|
|
5363
5446
|
}
|
|
5364
5447
|
};
|
|
5365
5448
|
};
|
|
@@ -5391,6 +5474,21 @@ var evaluateRepositoryRisk = (input, options = {}) => {
|
|
|
5391
5474
|
|
|
5392
5475
|
// src/application/run-analyze-command.ts
|
|
5393
5476
|
var resolveTargetPath = (inputPath, cwd) => resolve3(cwd, inputPath ?? ".");
|
|
5477
|
+
var riskProfileConfig = {
|
|
5478
|
+
default: void 0,
|
|
5479
|
+
personal: {
|
|
5480
|
+
evolutionFactorWeights: {
|
|
5481
|
+
frequency: 0.26,
|
|
5482
|
+
churn: 0.24,
|
|
5483
|
+
recentVolatility: 0.2,
|
|
5484
|
+
ownershipConcentration: 0.08,
|
|
5485
|
+
busFactorRisk: 0.04
|
|
5486
|
+
}
|
|
5487
|
+
}
|
|
5488
|
+
};
|
|
5489
|
+
var resolveRiskConfigForProfile = (riskProfile) => {
|
|
5490
|
+
return riskProfileConfig[riskProfile ?? "default"];
|
|
5491
|
+
};
|
|
5394
5492
|
var createExternalProgressReporter = (logger) => {
|
|
5395
5493
|
let lastLoggedProgress = 0;
|
|
5396
5494
|
return (event) => {
|
|
@@ -5558,8 +5656,12 @@ var runAnalyzeCommand = async (inputPath, authorIdentityMode, options = {}, logg
|
|
|
5558
5656
|
logger
|
|
5559
5657
|
);
|
|
5560
5658
|
logger.info("computing risk summary");
|
|
5561
|
-
const
|
|
5562
|
-
|
|
5659
|
+
const riskConfig = resolveRiskConfigForProfile(options.riskProfile);
|
|
5660
|
+
const risk = computeRepositoryRiskSummary({
|
|
5661
|
+
...analysisInputs,
|
|
5662
|
+
...riskConfig === void 0 ? {} : { config: riskConfig }
|
|
5663
|
+
});
|
|
5664
|
+
logger.info(`analysis completed (riskScore=${risk.riskScore})`);
|
|
5563
5665
|
return {
|
|
5564
5666
|
...analysisInputs,
|
|
5565
5667
|
risk
|
|
@@ -5579,7 +5681,14 @@ var buildAnalysisSnapshot = async (inputPath, authorIdentityMode, options, logge
|
|
|
5579
5681
|
},
|
|
5580
5682
|
logger
|
|
5581
5683
|
);
|
|
5582
|
-
const
|
|
5684
|
+
const riskConfig = resolveRiskConfigForProfile(options.riskProfile);
|
|
5685
|
+
const evaluation = evaluateRepositoryRisk(
|
|
5686
|
+
{
|
|
5687
|
+
...analysisInputs,
|
|
5688
|
+
...riskConfig === void 0 ? {} : { config: riskConfig }
|
|
5689
|
+
},
|
|
5690
|
+
{ explain: options.includeTrace }
|
|
5691
|
+
);
|
|
5583
5692
|
const summary = {
|
|
5584
5693
|
...analysisInputs,
|
|
5585
5694
|
risk: evaluation.summary
|
|
@@ -5590,6 +5699,7 @@ var buildAnalysisSnapshot = async (inputPath, authorIdentityMode, options, logge
|
|
|
5590
5699
|
analysisConfig: {
|
|
5591
5700
|
authorIdentityMode,
|
|
5592
5701
|
includeTrace: options.includeTrace,
|
|
5702
|
+
riskProfile: options.riskProfile ?? "default",
|
|
5593
5703
|
recentWindowDays: analysisInputs.evolution.available ? analysisInputs.evolution.metrics.recentWindowDays : options.recentWindowDays ?? null
|
|
5594
5704
|
}
|
|
5595
5705
|
});
|
|
@@ -5624,6 +5734,7 @@ var runCheckCommand = async (inputPath, authorIdentityMode, options, logger = cr
|
|
|
5624
5734
|
authorIdentityMode,
|
|
5625
5735
|
{
|
|
5626
5736
|
includeTrace: options.includeTrace,
|
|
5737
|
+
...options.riskProfile === void 0 ? {} : { riskProfile: options.riskProfile },
|
|
5627
5738
|
...options.recentWindowDays === void 0 ? {} : { recentWindowDays: options.recentWindowDays }
|
|
5628
5739
|
},
|
|
5629
5740
|
logger
|
|
@@ -5692,6 +5803,7 @@ var runCiCommand = async (inputPath, authorIdentityMode, options, logger = creat
|
|
|
5692
5803
|
authorIdentityMode,
|
|
5693
5804
|
{
|
|
5694
5805
|
includeTrace: options.includeTrace,
|
|
5806
|
+
...options.riskProfile === void 0 ? {} : { riskProfile: options.riskProfile },
|
|
5695
5807
|
...options.recentWindowDays === void 0 ? {} : { recentWindowDays: options.recentWindowDays }
|
|
5696
5808
|
},
|
|
5697
5809
|
logger
|
|
@@ -5750,6 +5862,7 @@ var runCiCommand = async (inputPath, authorIdentityMode, options, logger = creat
|
|
|
5750
5862
|
authorIdentityMode,
|
|
5751
5863
|
{
|
|
5752
5864
|
includeTrace: options.includeTrace,
|
|
5865
|
+
...options.riskProfile === void 0 ? {} : { riskProfile: options.riskProfile },
|
|
5753
5866
|
...options.recentWindowDays === void 0 ? {} : { recentWindowDays: options.recentWindowDays }
|
|
5754
5867
|
},
|
|
5755
5868
|
logger
|
|
@@ -5825,6 +5938,7 @@ var runReportCommand = async (inputPath, authorIdentityMode, options, logger = c
|
|
|
5825
5938
|
authorIdentityMode,
|
|
5826
5939
|
{
|
|
5827
5940
|
includeTrace: options.includeTrace,
|
|
5941
|
+
...options.riskProfile === void 0 ? {} : { riskProfile: options.riskProfile },
|
|
5828
5942
|
...options.recentWindowDays === void 0 ? {} : { recentWindowDays: options.recentWindowDays }
|
|
5829
5943
|
},
|
|
5830
5944
|
logger
|
|
@@ -5881,7 +5995,14 @@ var runExplainCommand = async (inputPath, authorIdentityMode, options, logger =
|
|
|
5881
5995
|
logger
|
|
5882
5996
|
);
|
|
5883
5997
|
logger.info("computing explainable risk summary");
|
|
5884
|
-
const
|
|
5998
|
+
const riskConfig = resolveRiskConfigForProfile(options.riskProfile);
|
|
5999
|
+
const evaluation = evaluateRepositoryRisk(
|
|
6000
|
+
{
|
|
6001
|
+
...analysisInputs,
|
|
6002
|
+
...riskConfig === void 0 ? {} : { config: riskConfig }
|
|
6003
|
+
},
|
|
6004
|
+
{ explain: true }
|
|
6005
|
+
);
|
|
5885
6006
|
if (evaluation.trace === void 0) {
|
|
5886
6007
|
throw new Error("risk trace unavailable");
|
|
5887
6008
|
}
|
|
@@ -5889,7 +6010,7 @@ var runExplainCommand = async (inputPath, authorIdentityMode, options, logger =
|
|
|
5889
6010
|
...analysisInputs,
|
|
5890
6011
|
risk: evaluation.summary
|
|
5891
6012
|
};
|
|
5892
|
-
logger.info(`explanation completed (
|
|
6013
|
+
logger.info(`explanation completed (riskScore=${summary.risk.riskScore})`);
|
|
5893
6014
|
return {
|
|
5894
6015
|
summary,
|
|
5895
6016
|
trace: evaluation.trace,
|
|
@@ -5908,8 +6029,12 @@ var parseRecentWindowDays = (value) => {
|
|
|
5908
6029
|
}
|
|
5909
6030
|
return parsed;
|
|
5910
6031
|
};
|
|
6032
|
+
var riskProfileOption = () => new Option(
|
|
6033
|
+
"--risk-profile <profile>",
|
|
6034
|
+
"risk profile: default (balanced) or personal (down-weights single-maintainer ownership penalties)"
|
|
6035
|
+
).choices(["default", "personal"]).default("default");
|
|
5911
6036
|
program.name("codesentinel").description("Structural and evolutionary risk analysis for TypeScript/JavaScript codebases").version(version);
|
|
5912
|
-
program.command("analyze").argument("[path]", "path to the project to analyze").addOption(
|
|
6037
|
+
program.command("analyze").argument("[path]", "path to the project to analyze").addOption(riskProfileOption()).addOption(
|
|
5913
6038
|
new Option(
|
|
5914
6039
|
"--author-identity <mode>",
|
|
5915
6040
|
"author identity mode: likely_merge (heuristic) or strict_email (deterministic)"
|
|
@@ -5932,7 +6057,7 @@ program.command("analyze").argument("[path]", "path to the project to analyze").
|
|
|
5932
6057
|
const summary = await runAnalyzeCommand(
|
|
5933
6058
|
path,
|
|
5934
6059
|
options.authorIdentity,
|
|
5935
|
-
{ recentWindowDays: options.recentWindowDays },
|
|
6060
|
+
{ recentWindowDays: options.recentWindowDays, riskProfile: options.riskProfile },
|
|
5936
6061
|
logger
|
|
5937
6062
|
);
|
|
5938
6063
|
const outputMode = options.json === true ? "json" : options.output;
|
|
@@ -5940,7 +6065,7 @@ program.command("analyze").argument("[path]", "path to the project to analyze").
|
|
|
5940
6065
|
`);
|
|
5941
6066
|
}
|
|
5942
6067
|
);
|
|
5943
|
-
program.command("explain").argument("[path]", "path to the project to analyze").addOption(
|
|
6068
|
+
program.command("explain").argument("[path]", "path to the project to analyze").addOption(riskProfileOption()).addOption(
|
|
5944
6069
|
new Option(
|
|
5945
6070
|
"--author-identity <mode>",
|
|
5946
6071
|
"author identity mode: likely_merge (heuristic) or strict_email (deterministic)"
|
|
@@ -5966,6 +6091,7 @@ program.command("explain").argument("[path]", "path to the project to analyze").
|
|
|
5966
6091
|
...options.module === void 0 ? {} : { module: options.module },
|
|
5967
6092
|
top: Number.isFinite(top) ? top : 5,
|
|
5968
6093
|
recentWindowDays: options.recentWindowDays,
|
|
6094
|
+
riskProfile: options.riskProfile,
|
|
5969
6095
|
format: options.format
|
|
5970
6096
|
};
|
|
5971
6097
|
const result = await runExplainCommand(path, options.authorIdentity, explainOptions, logger);
|
|
@@ -6003,7 +6129,7 @@ program.command("dependency-risk").argument("<dependency>", "dependency spec to
|
|
|
6003
6129
|
`);
|
|
6004
6130
|
}
|
|
6005
6131
|
);
|
|
6006
|
-
program.command("report").argument("[path]", "path to the project to analyze").addOption(
|
|
6132
|
+
program.command("report").argument("[path]", "path to the project to analyze").addOption(riskProfileOption()).addOption(
|
|
6007
6133
|
new Option(
|
|
6008
6134
|
"--author-identity <mode>",
|
|
6009
6135
|
"author identity mode: likely_merge (heuristic) or strict_email (deterministic)"
|
|
@@ -6032,6 +6158,7 @@ program.command("report").argument("[path]", "path to the project to analyze").a
|
|
|
6032
6158
|
...options.compare === void 0 ? {} : { comparePath: options.compare },
|
|
6033
6159
|
...options.snapshot === void 0 ? {} : { snapshotPath: options.snapshot },
|
|
6034
6160
|
includeTrace: options.trace,
|
|
6161
|
+
riskProfile: options.riskProfile,
|
|
6035
6162
|
recentWindowDays: options.recentWindowDays
|
|
6036
6163
|
},
|
|
6037
6164
|
logger
|
|
@@ -6083,7 +6210,7 @@ var buildGateConfigFromOptions = (options) => {
|
|
|
6083
6210
|
failOn: options.failOn
|
|
6084
6211
|
};
|
|
6085
6212
|
};
|
|
6086
|
-
program.command("check").argument("[path]", "path to the project to analyze").addOption(
|
|
6213
|
+
program.command("check").argument("[path]", "path to the project to analyze").addOption(riskProfileOption()).addOption(
|
|
6087
6214
|
new Option(
|
|
6088
6215
|
"--author-identity <mode>",
|
|
6089
6216
|
"author identity mode: likely_merge (heuristic) or strict_email (deterministic)"
|
|
@@ -6113,6 +6240,7 @@ program.command("check").argument("[path]", "path to the project to analyze").ad
|
|
|
6113
6240
|
{
|
|
6114
6241
|
...options.compare === void 0 ? {} : { baselinePath: options.compare },
|
|
6115
6242
|
includeTrace: options.trace,
|
|
6243
|
+
riskProfile: options.riskProfile,
|
|
6116
6244
|
recentWindowDays: options.recentWindowDays,
|
|
6117
6245
|
gateConfig,
|
|
6118
6246
|
outputFormat: options.format,
|
|
@@ -6136,7 +6264,7 @@ program.command("check").argument("[path]", "path to the project to analyze").ad
|
|
|
6136
6264
|
}
|
|
6137
6265
|
}
|
|
6138
6266
|
);
|
|
6139
|
-
program.command("ci").argument("[path]", "path to the project to analyze").addOption(
|
|
6267
|
+
program.command("ci").argument("[path]", "path to the project to analyze").addOption(riskProfileOption()).addOption(
|
|
6140
6268
|
new Option(
|
|
6141
6269
|
"--author-identity <mode>",
|
|
6142
6270
|
"author identity mode: likely_merge (heuristic) or strict_email (deterministic)"
|
|
@@ -6185,6 +6313,7 @@ program.command("ci").argument("[path]", "path to the project to analyze").addOp
|
|
|
6185
6313
|
...options.report === void 0 ? {} : { reportPath: options.report },
|
|
6186
6314
|
...options.jsonOutput === void 0 ? {} : { jsonOutputPath: options.jsonOutput },
|
|
6187
6315
|
includeTrace: options.trace,
|
|
6316
|
+
riskProfile: options.riskProfile,
|
|
6188
6317
|
recentWindowDays: options.recentWindowDays,
|
|
6189
6318
|
gateConfig
|
|
6190
6319
|
},
|