@aiready/context-analyzer 0.21.26 → 0.21.27
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/.turbo/turbo-build.log +32 -25
- package/.turbo/turbo-test.log +51 -87
- package/coverage/clover.xml +392 -1878
- package/coverage/coverage-final.json +15 -19
- package/coverage/index.html +48 -63
- package/coverage/src/analyzers/index.html +21 -21
- package/coverage/src/analyzers/python-context.ts.html +96 -96
- package/coverage/src/ast-utils.ts.html +34 -109
- package/coverage/src/classifier.ts.html +104 -104
- package/coverage/src/classify/classification-patterns.ts.html +1 -1
- package/coverage/src/classify/file-classifiers.ts.html +1 -1
- package/coverage/src/classify/index.html +1 -1
- package/coverage/src/cluster-detector.ts.html +72 -72
- package/coverage/src/defaults.ts.html +1 -1
- package/coverage/src/graph-builder.ts.html +131 -131
- package/coverage/src/index.html +101 -116
- package/coverage/src/index.ts.html +2 -2
- package/coverage/src/issue-analyzer.ts.html +32 -83
- package/coverage/src/mapper.ts.html +20 -2
- package/coverage/src/metrics.ts.html +127 -130
- package/coverage/src/orchestrator.ts.html +13 -13
- package/coverage/src/provider.ts.html +19 -19
- package/coverage/src/remediation.ts.html +59 -59
- package/coverage/src/report/console-report.ts.html +2 -2
- package/coverage/src/report/html-report.ts.html +60 -84
- package/coverage/src/report/index.html +7 -7
- package/coverage/src/report/interactive-setup.ts.html +1 -1
- package/coverage/src/scoring.ts.html +62 -62
- package/coverage/src/semantic/co-usage.ts.html +1 -1
- package/coverage/src/semantic/consolidation.ts.html +1 -1
- package/coverage/src/semantic/domain-inference.ts.html +1 -1
- package/coverage/src/semantic/index.html +1 -1
- package/coverage/src/semantic/type-graph.ts.html +1 -1
- package/coverage/src/summary.ts.html +67 -67
- package/coverage/src/types.ts.html +1 -1
- package/coverage/src/utils/dependency-graph-utils.ts.html +41 -41
- package/coverage/src/utils/index.html +21 -21
- package/coverage/src/utils/string-utils.ts.html +1 -1
- package/dist/chunk-22ZO4EKZ.mjs +1297 -0
- package/dist/chunk-4U4LDWGF.mjs +360 -0
- package/dist/chunk-BA7QGUHN.mjs +1722 -0
- package/dist/chunk-BCEZGRXI.mjs +1297 -0
- package/dist/chunk-BQCISA2F.mjs +91 -0
- package/dist/chunk-EMYD7NS6.mjs +137 -0
- package/dist/chunk-EWFR366Y.mjs +1740 -0
- package/dist/chunk-FO6YT6RG.mjs +1751 -0
- package/dist/chunk-J3SZQZNU.mjs +221 -0
- package/dist/chunk-OZE3FVZT.mjs +1089 -0
- package/dist/chunk-WHB7QI7N.mjs +91 -0
- package/dist/cli-action-CXIHOVAC.mjs +95 -0
- package/dist/cli-action-SA7SCYNV.mjs +95 -0
- package/dist/cli-action-YAJOJCXJ.mjs +95 -0
- package/dist/cli.js +688 -566
- package/dist/cli.mjs +4 -88
- package/dist/index.js +889 -773
- package/dist/index.mjs +21 -14
- package/dist/orchestrator-3L3NAZYP.mjs +10 -0
- package/dist/orchestrator-MONOZHVW.mjs +10 -0
- package/dist/orchestrator-ZR7JSKWI.mjs +10 -0
- package/dist/summary-7PZVW72O.mjs +7 -0
- package/dist/summary-LKUCJAIS.mjs +7 -0
- package/package.json +2 -2
- package/src/__tests__/analyzer.test.ts +1 -1
- package/src/__tests__/enhanced-cohesion.test.ts +4 -1
- package/src/__tests__/orchestrator.test.ts +19 -4
- package/src/__tests__/python-context.test.ts +6 -0
- package/src/__tests__/report/html-report.test.ts +8 -2
- package/src/ast-utils.ts +1 -26
- package/src/cli-definition.ts +4 -2
- package/src/issue-analyzer.ts +4 -19
- package/src/metrics.ts +1 -2
- package/src/provider.ts +4 -4
- package/src/report/html-report.ts +43 -59
- package/coverage/dist/chunk-64U3PNO3.mjs.html +0 -367
- package/coverage/dist/chunk-J3MUOWHC.mjs.html +0 -5326
- package/coverage/dist/index.html +0 -146
- package/coverage/dist/index.mjs.html +0 -1396
- package/coverage/src/analyzer.ts.html +0 -88
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import {
|
|
2
|
+
calculatePathEntropy
|
|
3
|
+
} from "./chunk-4U4LDWGF.mjs";
|
|
4
|
+
|
|
5
|
+
// src/summary.ts
|
|
6
|
+
import { GLOBAL_SCAN_OPTIONS } from "@aiready/core";
|
|
7
|
+
function generateSummary(results, options = {}) {
|
|
8
|
+
const config = options ? Object.fromEntries(
|
|
9
|
+
Object.entries(options).filter(
|
|
10
|
+
([key]) => !GLOBAL_SCAN_OPTIONS.includes(key) || key === "rootDir"
|
|
11
|
+
)
|
|
12
|
+
) : {};
|
|
13
|
+
const totalFiles = results.length;
|
|
14
|
+
const totalTokens = results.reduce((sum, r) => sum + r.tokenCost, 0);
|
|
15
|
+
const avgContextBudget = totalFiles > 0 ? results.reduce((sum, r) => sum + r.contextBudget, 0) / totalFiles : 0;
|
|
16
|
+
const deepFiles = results.filter((r) => r.importDepth > 5).map((r) => ({ file: r.file, depth: r.importDepth }));
|
|
17
|
+
const maxImportDepth = Math.max(0, ...results.map((r) => r.importDepth));
|
|
18
|
+
const moduleMap = /* @__PURE__ */ new Map();
|
|
19
|
+
results.forEach((r) => {
|
|
20
|
+
const parts = r.file.split("/");
|
|
21
|
+
let domain = "root";
|
|
22
|
+
if (parts.length > 2) {
|
|
23
|
+
domain = parts.slice(0, 2).join("/");
|
|
24
|
+
}
|
|
25
|
+
if (!moduleMap.has(domain)) moduleMap.set(domain, []);
|
|
26
|
+
moduleMap.get(domain).push(r);
|
|
27
|
+
});
|
|
28
|
+
const fragmentedModules = [];
|
|
29
|
+
moduleMap.forEach((files, domain) => {
|
|
30
|
+
const clusterTokens = files.reduce((sum, f) => sum + f.tokenCost, 0);
|
|
31
|
+
const filePaths = files.map((f) => f.file);
|
|
32
|
+
const avgEntropy = calculatePathEntropy(filePaths);
|
|
33
|
+
const fragmentationScore = Math.min(1, avgEntropy * (files.length / 10));
|
|
34
|
+
if (fragmentationScore > 0.4) {
|
|
35
|
+
fragmentedModules.push({
|
|
36
|
+
domain,
|
|
37
|
+
files: filePaths,
|
|
38
|
+
fragmentationScore,
|
|
39
|
+
totalTokens: clusterTokens,
|
|
40
|
+
avgCohesion: files.reduce((sum, f) => sum + f.cohesionScore, 0) / files.length,
|
|
41
|
+
suggestedStructure: {
|
|
42
|
+
targetFiles: Math.ceil(files.length / 2),
|
|
43
|
+
consolidationPlan: [
|
|
44
|
+
`Consolidate ${files.length} files in ${domain} into fewer modules`
|
|
45
|
+
]
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
fragmentedModules.sort((a, b) => b.fragmentationScore - a.fragmentationScore);
|
|
51
|
+
const avgFragmentation = fragmentedModules.length > 0 ? fragmentedModules.reduce((sum, m) => sum + m.fragmentationScore, 0) / fragmentedModules.length : 0;
|
|
52
|
+
const avgCohesion = results.reduce((sum, r) => sum + r.cohesionScore, 0) / (totalFiles || 1);
|
|
53
|
+
const lowCohesionFiles = results.filter((r) => r.cohesionScore < 0.4).map((r) => ({ file: r.file, score: r.cohesionScore }));
|
|
54
|
+
const criticalIssues = results.filter(
|
|
55
|
+
(r) => r.severity === "critical"
|
|
56
|
+
).length;
|
|
57
|
+
const majorIssues = results.filter((r) => r.severity === "major").length;
|
|
58
|
+
const minorIssues = results.filter((r) => r.severity === "minor").length;
|
|
59
|
+
const totalPotentialSavings = results.reduce(
|
|
60
|
+
(sum, r) => sum + (r.potentialSavings || 0),
|
|
61
|
+
0
|
|
62
|
+
);
|
|
63
|
+
const topExpensiveFiles = [...results].sort((a, b) => b.contextBudget - a.contextBudget).slice(0, 10).map((r) => ({
|
|
64
|
+
file: r.file,
|
|
65
|
+
contextBudget: r.contextBudget,
|
|
66
|
+
severity: r.severity
|
|
67
|
+
}));
|
|
68
|
+
return {
|
|
69
|
+
totalFiles,
|
|
70
|
+
totalTokens,
|
|
71
|
+
avgContextBudget,
|
|
72
|
+
maxContextBudget: Math.max(0, ...results.map((r) => r.contextBudget)),
|
|
73
|
+
avgImportDepth: results.reduce((sum, r) => sum + r.importDepth, 0) / (totalFiles || 1),
|
|
74
|
+
maxImportDepth,
|
|
75
|
+
deepFiles,
|
|
76
|
+
avgFragmentation,
|
|
77
|
+
fragmentedModules,
|
|
78
|
+
avgCohesion,
|
|
79
|
+
lowCohesionFiles,
|
|
80
|
+
criticalIssues,
|
|
81
|
+
majorIssues,
|
|
82
|
+
minorIssues,
|
|
83
|
+
totalPotentialSavings,
|
|
84
|
+
topExpensiveFiles,
|
|
85
|
+
config
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export {
|
|
90
|
+
generateSummary
|
|
91
|
+
};
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import {
|
|
2
|
+
displayConsoleReport,
|
|
3
|
+
generateHTMLReport,
|
|
4
|
+
runInteractiveSetup
|
|
5
|
+
} from "./chunk-J3SZQZNU.mjs";
|
|
6
|
+
import {
|
|
7
|
+
analyzeContext
|
|
8
|
+
} from "./chunk-OZE3FVZT.mjs";
|
|
9
|
+
import "./chunk-64U3PNO3.mjs";
|
|
10
|
+
import {
|
|
11
|
+
generateSummary
|
|
12
|
+
} from "./chunk-WHB7QI7N.mjs";
|
|
13
|
+
import "./chunk-4U4LDWGF.mjs";
|
|
14
|
+
|
|
15
|
+
// src/cli-action.ts
|
|
16
|
+
import {
|
|
17
|
+
loadMergedConfig,
|
|
18
|
+
handleJSONOutput,
|
|
19
|
+
handleCLIError,
|
|
20
|
+
getElapsedTime,
|
|
21
|
+
resolveOutputPath
|
|
22
|
+
} from "@aiready/core";
|
|
23
|
+
import chalk from "chalk";
|
|
24
|
+
import { writeFileSync } from "fs";
|
|
25
|
+
async function contextActionHandler(directory, options) {
|
|
26
|
+
console.log(chalk.blue("\u{1F50D} Analyzing context window costs...\n"));
|
|
27
|
+
const startTime = Date.now();
|
|
28
|
+
try {
|
|
29
|
+
const defaults = {
|
|
30
|
+
maxDepth: 5,
|
|
31
|
+
maxContextBudget: 1e4,
|
|
32
|
+
minCohesion: 0.6,
|
|
33
|
+
maxFragmentation: 0.5,
|
|
34
|
+
focus: "all",
|
|
35
|
+
includeNodeModules: false,
|
|
36
|
+
include: void 0,
|
|
37
|
+
exclude: void 0,
|
|
38
|
+
maxResults: 10
|
|
39
|
+
};
|
|
40
|
+
let finalOptions = await loadMergedConfig(directory, defaults, {
|
|
41
|
+
maxDepth: options.maxDepth ? parseInt(options.maxDepth) : void 0,
|
|
42
|
+
maxContextBudget: options.maxContext ? parseInt(options.maxContext) : void 0,
|
|
43
|
+
minCohesion: options.minCohesion ? parseFloat(options.minCohesion) : void 0,
|
|
44
|
+
maxFragmentation: options.maxFragmentation ? parseFloat(options.maxFragmentation) : void 0,
|
|
45
|
+
focus: options.focus || void 0,
|
|
46
|
+
includeNodeModules: options.includeNodeModules,
|
|
47
|
+
include: options.include?.split(","),
|
|
48
|
+
exclude: options.exclude?.split(","),
|
|
49
|
+
maxResults: options.maxResults ? parseInt(options.maxResults) : void 0
|
|
50
|
+
});
|
|
51
|
+
if (options.interactive) {
|
|
52
|
+
finalOptions = await runInteractiveSetup(directory, finalOptions);
|
|
53
|
+
}
|
|
54
|
+
const results = await analyzeContext(finalOptions);
|
|
55
|
+
const summary = generateSummary(results, finalOptions);
|
|
56
|
+
const duration = getElapsedTime(startTime);
|
|
57
|
+
if (options.output === "json") {
|
|
58
|
+
handleJSONOutput(
|
|
59
|
+
{
|
|
60
|
+
summary: {
|
|
61
|
+
...summary,
|
|
62
|
+
executionTime: duration,
|
|
63
|
+
config: {
|
|
64
|
+
scan: { tools: ["context"] },
|
|
65
|
+
tools: { context: finalOptions }
|
|
66
|
+
},
|
|
67
|
+
toolConfigs: { context: finalOptions }
|
|
68
|
+
},
|
|
69
|
+
context: { results }
|
|
70
|
+
},
|
|
71
|
+
options.outputFile
|
|
72
|
+
);
|
|
73
|
+
} else if (options.output === "html") {
|
|
74
|
+
const html = generateHTMLReport(summary, results);
|
|
75
|
+
const outputPath = resolveOutputPath(
|
|
76
|
+
directory,
|
|
77
|
+
options.outputFile,
|
|
78
|
+
"context-report.html"
|
|
79
|
+
);
|
|
80
|
+
writeFileSync(outputPath, html, "utf-8");
|
|
81
|
+
console.log(chalk.green(`
|
|
82
|
+
\u2705 HTML report saved to: ${outputPath}`));
|
|
83
|
+
} else {
|
|
84
|
+
displayConsoleReport(summary, results, finalOptions.maxResults);
|
|
85
|
+
console.log(chalk.dim(`
|
|
86
|
+
\u2728 Analysis completed in ${duration}ms
|
|
87
|
+
`));
|
|
88
|
+
}
|
|
89
|
+
} catch (error) {
|
|
90
|
+
handleCLIError(error, "context-analyzer");
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
export {
|
|
94
|
+
contextActionHandler
|
|
95
|
+
};
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import {
|
|
2
|
+
displayConsoleReport,
|
|
3
|
+
generateHTMLReport,
|
|
4
|
+
runInteractiveSetup
|
|
5
|
+
} from "./chunk-J3SZQZNU.mjs";
|
|
6
|
+
import {
|
|
7
|
+
analyzeContext
|
|
8
|
+
} from "./chunk-BCEZGRXI.mjs";
|
|
9
|
+
import "./chunk-64U3PNO3.mjs";
|
|
10
|
+
import {
|
|
11
|
+
generateSummary
|
|
12
|
+
} from "./chunk-BQCISA2F.mjs";
|
|
13
|
+
import "./chunk-EMYD7NS6.mjs";
|
|
14
|
+
|
|
15
|
+
// src/cli-action.ts
|
|
16
|
+
import {
|
|
17
|
+
loadMergedConfig,
|
|
18
|
+
handleJSONOutput,
|
|
19
|
+
handleCLIError,
|
|
20
|
+
getElapsedTime,
|
|
21
|
+
resolveOutputPath
|
|
22
|
+
} from "@aiready/core";
|
|
23
|
+
import chalk from "chalk";
|
|
24
|
+
import { writeFileSync } from "fs";
|
|
25
|
+
async function contextActionHandler(directory, options) {
|
|
26
|
+
console.log(chalk.blue("\u{1F50D} Analyzing context window costs...\n"));
|
|
27
|
+
const startTime = Date.now();
|
|
28
|
+
try {
|
|
29
|
+
const defaults = {
|
|
30
|
+
maxDepth: 5,
|
|
31
|
+
maxContextBudget: 1e4,
|
|
32
|
+
minCohesion: 0.6,
|
|
33
|
+
maxFragmentation: 0.5,
|
|
34
|
+
focus: "all",
|
|
35
|
+
includeNodeModules: false,
|
|
36
|
+
include: void 0,
|
|
37
|
+
exclude: void 0,
|
|
38
|
+
maxResults: 10
|
|
39
|
+
};
|
|
40
|
+
let finalOptions = await loadMergedConfig(directory, defaults, {
|
|
41
|
+
maxDepth: options.maxDepth ? parseInt(options.maxDepth) : void 0,
|
|
42
|
+
maxContextBudget: options.maxContext ? parseInt(options.maxContext) : void 0,
|
|
43
|
+
minCohesion: options.minCohesion ? parseFloat(options.minCohesion) : void 0,
|
|
44
|
+
maxFragmentation: options.maxFragmentation ? parseFloat(options.maxFragmentation) : void 0,
|
|
45
|
+
focus: options.focus || void 0,
|
|
46
|
+
includeNodeModules: options.includeNodeModules,
|
|
47
|
+
include: options.include?.split(","),
|
|
48
|
+
exclude: options.exclude?.split(","),
|
|
49
|
+
maxResults: options.maxResults ? parseInt(options.maxResults) : void 0
|
|
50
|
+
});
|
|
51
|
+
if (options.interactive) {
|
|
52
|
+
finalOptions = await runInteractiveSetup(directory, finalOptions);
|
|
53
|
+
}
|
|
54
|
+
const results = await analyzeContext(finalOptions);
|
|
55
|
+
const summary = generateSummary(results, finalOptions);
|
|
56
|
+
const duration = getElapsedTime(startTime);
|
|
57
|
+
if (options.output === "json") {
|
|
58
|
+
handleJSONOutput(
|
|
59
|
+
{
|
|
60
|
+
summary: {
|
|
61
|
+
...summary,
|
|
62
|
+
executionTime: duration,
|
|
63
|
+
config: {
|
|
64
|
+
scan: { tools: ["context"] },
|
|
65
|
+
tools: { context: finalOptions }
|
|
66
|
+
},
|
|
67
|
+
toolConfigs: { context: finalOptions }
|
|
68
|
+
},
|
|
69
|
+
context: { results }
|
|
70
|
+
},
|
|
71
|
+
options.outputFile
|
|
72
|
+
);
|
|
73
|
+
} else if (options.output === "html") {
|
|
74
|
+
const html = generateHTMLReport(summary, results);
|
|
75
|
+
const outputPath = resolveOutputPath(
|
|
76
|
+
directory,
|
|
77
|
+
options.outputFile,
|
|
78
|
+
"context-report.html"
|
|
79
|
+
);
|
|
80
|
+
writeFileSync(outputPath, html, "utf-8");
|
|
81
|
+
console.log(chalk.green(`
|
|
82
|
+
\u2705 HTML report saved to: ${outputPath}`));
|
|
83
|
+
} else {
|
|
84
|
+
displayConsoleReport(summary, results, finalOptions.maxResults);
|
|
85
|
+
console.log(chalk.dim(`
|
|
86
|
+
\u2728 Analysis completed in ${duration}ms
|
|
87
|
+
`));
|
|
88
|
+
}
|
|
89
|
+
} catch (error) {
|
|
90
|
+
handleCLIError(error, "context-analyzer");
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
export {
|
|
94
|
+
contextActionHandler
|
|
95
|
+
};
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import {
|
|
2
|
+
displayConsoleReport,
|
|
3
|
+
generateHTMLReport,
|
|
4
|
+
runInteractiveSetup
|
|
5
|
+
} from "./chunk-J3SZQZNU.mjs";
|
|
6
|
+
import {
|
|
7
|
+
analyzeContext
|
|
8
|
+
} from "./chunk-22ZO4EKZ.mjs";
|
|
9
|
+
import "./chunk-64U3PNO3.mjs";
|
|
10
|
+
import {
|
|
11
|
+
generateSummary
|
|
12
|
+
} from "./chunk-BQCISA2F.mjs";
|
|
13
|
+
import "./chunk-EMYD7NS6.mjs";
|
|
14
|
+
|
|
15
|
+
// src/cli-action.ts
|
|
16
|
+
import {
|
|
17
|
+
loadMergedConfig,
|
|
18
|
+
handleJSONOutput,
|
|
19
|
+
handleCLIError,
|
|
20
|
+
getElapsedTime,
|
|
21
|
+
resolveOutputPath
|
|
22
|
+
} from "@aiready/core";
|
|
23
|
+
import chalk from "chalk";
|
|
24
|
+
import { writeFileSync } from "fs";
|
|
25
|
+
async function contextActionHandler(directory, options) {
|
|
26
|
+
console.log(chalk.blue("\u{1F50D} Analyzing context window costs...\n"));
|
|
27
|
+
const startTime = Date.now();
|
|
28
|
+
try {
|
|
29
|
+
const defaults = {
|
|
30
|
+
maxDepth: 5,
|
|
31
|
+
maxContextBudget: 1e4,
|
|
32
|
+
minCohesion: 0.6,
|
|
33
|
+
maxFragmentation: 0.5,
|
|
34
|
+
focus: "all",
|
|
35
|
+
includeNodeModules: false,
|
|
36
|
+
include: void 0,
|
|
37
|
+
exclude: void 0,
|
|
38
|
+
maxResults: 10
|
|
39
|
+
};
|
|
40
|
+
let finalOptions = await loadMergedConfig(directory, defaults, {
|
|
41
|
+
maxDepth: options.maxDepth ? parseInt(options.maxDepth) : void 0,
|
|
42
|
+
maxContextBudget: options.maxContext ? parseInt(options.maxContext) : void 0,
|
|
43
|
+
minCohesion: options.minCohesion ? parseFloat(options.minCohesion) : void 0,
|
|
44
|
+
maxFragmentation: options.maxFragmentation ? parseFloat(options.maxFragmentation) : void 0,
|
|
45
|
+
focus: options.focus || void 0,
|
|
46
|
+
includeNodeModules: options.includeNodeModules,
|
|
47
|
+
include: options.include?.split(","),
|
|
48
|
+
exclude: options.exclude?.split(","),
|
|
49
|
+
maxResults: options.maxResults ? parseInt(options.maxResults) : void 0
|
|
50
|
+
});
|
|
51
|
+
if (options.interactive) {
|
|
52
|
+
finalOptions = await runInteractiveSetup(directory, finalOptions);
|
|
53
|
+
}
|
|
54
|
+
const results = await analyzeContext(finalOptions);
|
|
55
|
+
const summary = generateSummary(results, finalOptions);
|
|
56
|
+
const duration = getElapsedTime(startTime);
|
|
57
|
+
if (options.output === "json") {
|
|
58
|
+
handleJSONOutput(
|
|
59
|
+
{
|
|
60
|
+
summary: {
|
|
61
|
+
...summary,
|
|
62
|
+
executionTime: duration,
|
|
63
|
+
config: {
|
|
64
|
+
scan: { tools: ["context"] },
|
|
65
|
+
tools: { context: finalOptions }
|
|
66
|
+
},
|
|
67
|
+
toolConfigs: { context: finalOptions }
|
|
68
|
+
},
|
|
69
|
+
context: { results }
|
|
70
|
+
},
|
|
71
|
+
options.outputFile
|
|
72
|
+
);
|
|
73
|
+
} else if (options.output === "html") {
|
|
74
|
+
const html = generateHTMLReport(summary, results);
|
|
75
|
+
const outputPath = resolveOutputPath(
|
|
76
|
+
directory,
|
|
77
|
+
options.outputFile,
|
|
78
|
+
"context-report.html"
|
|
79
|
+
);
|
|
80
|
+
writeFileSync(outputPath, html, "utf-8");
|
|
81
|
+
console.log(chalk.green(`
|
|
82
|
+
\u2705 HTML report saved to: ${outputPath}`));
|
|
83
|
+
} else {
|
|
84
|
+
displayConsoleReport(summary, results, finalOptions.maxResults);
|
|
85
|
+
console.log(chalk.dim(`
|
|
86
|
+
\u2728 Analysis completed in ${duration}ms
|
|
87
|
+
`));
|
|
88
|
+
}
|
|
89
|
+
} catch (error) {
|
|
90
|
+
handleCLIError(error, "context-analyzer");
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
export {
|
|
94
|
+
contextActionHandler
|
|
95
|
+
};
|