@vyuhlabs/dxkit 2.6.0 → 2.7.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/CHANGELOG.md +54 -13
- package/README.md +208 -459
- package/dist/analyzers/bom/discovery.d.ts +3 -4
- package/dist/analyzers/bom/discovery.d.ts.map +1 -1
- package/dist/analyzers/bom/discovery.js +3 -4
- package/dist/analyzers/bom/discovery.js.map +1 -1
- package/dist/analyzers/bom/types.d.ts +1 -1
- package/dist/analyzers/dashboard/index.d.ts.map +1 -1
- package/dist/analyzers/dashboard/index.js +42 -5
- package/dist/analyzers/dashboard/index.js.map +1 -1
- package/dist/analyzers/quality/detailed.d.ts +8 -1
- package/dist/analyzers/quality/detailed.d.ts.map +1 -1
- package/dist/analyzers/quality/detailed.js +43 -10
- package/dist/analyzers/quality/detailed.js.map +1 -1
- package/dist/analyzers/security/detailed.d.ts +8 -1
- package/dist/analyzers/security/detailed.d.ts.map +1 -1
- package/dist/analyzers/security/detailed.js +14 -1
- package/dist/analyzers/security/detailed.js.map +1 -1
- package/dist/analyzers/tests/detailed.d.ts +8 -1
- package/dist/analyzers/tests/detailed.d.ts.map +1 -1
- package/dist/analyzers/tests/detailed.js +26 -7
- package/dist/analyzers/tests/detailed.js.map +1 -1
- package/dist/analyzers/tools/cloc.js +3 -3
- package/dist/analyzers/tools/cloc.js.map +1 -1
- package/dist/analyzers/tools/exclusions.d.ts +12 -12
- package/dist/analyzers/tools/exclusions.d.ts.map +1 -1
- package/dist/analyzers/tools/exclusions.js +27 -13
- package/dist/analyzers/tools/exclusions.js.map +1 -1
- package/dist/analyzers/tools/graphify.d.ts +39 -5
- package/dist/analyzers/tools/graphify.d.ts.map +1 -1
- package/dist/analyzers/tools/graphify.js +609 -45
- package/dist/analyzers/tools/graphify.js.map +1 -1
- package/dist/analyzers/tools/nuget-package-reference.d.ts +4 -4
- package/dist/analyzers/tools/nuget-package-reference.js +4 -4
- package/dist/analyzers/tools/osv-scanner-fix.d.ts +4 -5
- package/dist/analyzers/tools/osv-scanner-fix.d.ts.map +1 -1
- package/dist/analyzers/tools/osv-scanner-fix.js +4 -5
- package/dist/analyzers/tools/osv-scanner-fix.js.map +1 -1
- package/dist/analyzers/tools/parallel.d.ts.map +1 -1
- package/dist/analyzers/tools/parallel.js +7 -0
- package/dist/analyzers/tools/parallel.js.map +1 -1
- package/dist/analyzers/tools/vendored-advisor.d.ts.map +1 -1
- package/dist/analyzers/tools/vendored-advisor.js +3 -4
- package/dist/analyzers/tools/vendored-advisor.js.map +1 -1
- package/dist/analyzers/xlsx/licenses.d.ts +7 -7
- package/dist/analyzers/xlsx/licenses.js +7 -7
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +80 -3
- package/dist/cli.js.map +1 -1
- package/dist/dashboard/graph-adapter.d.ts +151 -0
- package/dist/dashboard/graph-adapter.d.ts.map +1 -0
- package/dist/dashboard/graph-adapter.js +415 -0
- package/dist/dashboard/graph-adapter.js.map +1 -0
- package/dist/dashboard/graph-tab.d.ts +109 -0
- package/dist/dashboard/graph-tab.d.ts.map +1 -0
- package/dist/dashboard/graph-tab.js +297 -0
- package/dist/dashboard/graph-tab.js.map +1 -0
- package/dist/dashboard/vendor/vis-network.min.js +34 -0
- package/dist/explore/cli/api-surface.d.ts +12 -0
- package/dist/explore/cli/api-surface.d.ts.map +1 -0
- package/dist/explore/cli/api-surface.js +57 -0
- package/dist/explore/cli/api-surface.js.map +1 -0
- package/dist/explore/cli/communities.d.ts +10 -0
- package/dist/explore/cli/communities.d.ts.map +1 -0
- package/dist/explore/cli/communities.js +47 -0
- package/dist/explore/cli/communities.js.map +1 -0
- package/dist/explore/cli/context.d.ts +16 -0
- package/dist/explore/cli/context.d.ts.map +1 -0
- package/dist/explore/cli/context.js +118 -0
- package/dist/explore/cli/context.js.map +1 -0
- package/dist/explore/cli/entry-points.d.ts +12 -0
- package/dist/explore/cli/entry-points.d.ts.map +1 -0
- package/dist/explore/cli/entry-points.js +85 -0
- package/dist/explore/cli/entry-points.js.map +1 -0
- package/dist/explore/cli/feature.d.ts +16 -0
- package/dist/explore/cli/feature.d.ts.map +1 -0
- package/dist/explore/cli/feature.js +89 -0
- package/dist/explore/cli/feature.js.map +1 -0
- package/dist/explore/cli/file.d.ts +12 -0
- package/dist/explore/cli/file.d.ts.map +1 -0
- package/dist/explore/cli/file.js +139 -0
- package/dist/explore/cli/file.js.map +1 -0
- package/dist/explore/cli/hot-files.d.ts +11 -0
- package/dist/explore/cli/hot-files.d.ts.map +1 -0
- package/dist/explore/cli/hot-files.js +63 -0
- package/dist/explore/cli/hot-files.js.map +1 -0
- package/dist/explore/context-hook.d.ts +42 -0
- package/dist/explore/context-hook.d.ts.map +1 -0
- package/dist/explore/context-hook.js +131 -0
- package/dist/explore/context-hook.js.map +1 -0
- package/dist/explore/finding-context.d.ts +69 -0
- package/dist/explore/finding-context.d.ts.map +1 -0
- package/dist/explore/finding-context.js +102 -0
- package/dist/explore/finding-context.js.map +1 -0
- package/dist/explore/format.d.ts +64 -0
- package/dist/explore/format.d.ts.map +1 -0
- package/dist/explore/format.js +99 -0
- package/dist/explore/format.js.map +1 -0
- package/dist/explore/load.d.ts +50 -0
- package/dist/explore/load.d.ts.map +1 -0
- package/dist/explore/load.js +197 -0
- package/dist/explore/load.js.map +1 -0
- package/dist/explore/queries.d.ts +413 -0
- package/dist/explore/queries.d.ts.map +1 -0
- package/dist/explore/queries.js +855 -0
- package/dist/explore/queries.js.map +1 -0
- package/dist/explore/types.d.ts +130 -0
- package/dist/explore/types.d.ts.map +1 -0
- package/dist/explore/types.js +28 -0
- package/dist/explore/types.js.map +1 -0
- package/dist/explore-cli.d.ts +45 -0
- package/dist/explore-cli.d.ts.map +1 -0
- package/dist/explore-cli.js +213 -0
- package/dist/explore-cli.js.map +1 -0
- package/dist/generator.d.ts.map +1 -1
- package/dist/generator.js +19 -0
- package/dist/generator.js.map +1 -1
- package/dist/languages/csharp.d.ts.map +1 -1
- package/dist/languages/csharp.js +31 -11
- package/dist/languages/csharp.js.map +1 -1
- package/dist/languages/go.d.ts.map +1 -1
- package/dist/languages/go.js +4 -0
- package/dist/languages/go.js.map +1 -1
- package/dist/languages/index.d.ts +27 -0
- package/dist/languages/index.d.ts.map +1 -1
- package/dist/languages/index.js +35 -0
- package/dist/languages/index.js.map +1 -1
- package/dist/languages/java.d.ts.map +1 -1
- package/dist/languages/java.js +4 -0
- package/dist/languages/java.js.map +1 -1
- package/dist/languages/kotlin.d.ts.map +1 -1
- package/dist/languages/kotlin.js +4 -0
- package/dist/languages/kotlin.js.map +1 -1
- package/dist/languages/python.d.ts.map +1 -1
- package/dist/languages/python.js +4 -0
- package/dist/languages/python.js.map +1 -1
- package/dist/languages/ruby.d.ts.map +1 -1
- package/dist/languages/ruby.js +4 -0
- package/dist/languages/ruby.js.map +1 -1
- package/dist/languages/rust.d.ts.map +1 -1
- package/dist/languages/rust.js +4 -0
- package/dist/languages/rust.js.map +1 -1
- package/dist/languages/types.d.ts +54 -0
- package/dist/languages/types.d.ts.map +1 -1
- package/dist/languages/typescript.d.ts.map +1 -1
- package/dist/languages/typescript.js +5 -1
- package/dist/languages/typescript.js.map +1 -1
- package/package.json +2 -1
- package/templates/.claude/skills/dxkit-action/SKILL.md +21 -1
- package/templates/.claude/skills/dxkit-reports/SKILL.md +3 -1
- package/templates/AGENTS.md.template +8 -1
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* `vyuh-dxkit explore file <path>` — drill into a single file's
|
|
4
|
+
* neighborhood. Per CLAUDE.md Rule 12: graph traversal flows through
|
|
5
|
+
* queries.ts.
|
|
6
|
+
*
|
|
7
|
+
* If the user passes an absolute path, convert to project-relative
|
|
8
|
+
* (the graph artifact uses project-relative paths throughout).
|
|
9
|
+
*/
|
|
10
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
13
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
14
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
15
|
+
}
|
|
16
|
+
Object.defineProperty(o, k2, desc);
|
|
17
|
+
}) : (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
o[k2] = m[k];
|
|
20
|
+
}));
|
|
21
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
22
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
23
|
+
}) : function(o, v) {
|
|
24
|
+
o["default"] = v;
|
|
25
|
+
});
|
|
26
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
27
|
+
var ownKeys = function(o) {
|
|
28
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
29
|
+
var ar = [];
|
|
30
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
31
|
+
return ar;
|
|
32
|
+
};
|
|
33
|
+
return ownKeys(o);
|
|
34
|
+
};
|
|
35
|
+
return function (mod) {
|
|
36
|
+
if (mod && mod.__esModule) return mod;
|
|
37
|
+
var result = {};
|
|
38
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
39
|
+
__setModuleDefault(result, mod);
|
|
40
|
+
return result;
|
|
41
|
+
};
|
|
42
|
+
})();
|
|
43
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
44
|
+
exports.runFile = runFile;
|
|
45
|
+
const path = __importStar(require("node:path"));
|
|
46
|
+
const queries_1 = require("../queries");
|
|
47
|
+
const format_1 = require("../format");
|
|
48
|
+
function runFile(graph, positionals, values, cwd) {
|
|
49
|
+
const rawPath = positionals[0];
|
|
50
|
+
if (!rawPath) {
|
|
51
|
+
process.stderr.write('Usage: vyuh-dxkit explore file <path>\nProvide a path (relative or absolute) to a source file in the repo.\n');
|
|
52
|
+
process.exit(1);
|
|
53
|
+
}
|
|
54
|
+
// Convert absolute to project-relative if needed. Graphify writes
|
|
55
|
+
// project-relative paths to graph.json so the lookup key must
|
|
56
|
+
// match that shape.
|
|
57
|
+
const resolved = path.isAbsolute(rawPath)
|
|
58
|
+
? path.relative(cwd, rawPath).replace(/\\/g, '/')
|
|
59
|
+
: rawPath.replace(/\\/g, '/');
|
|
60
|
+
const result = (0, queries_1.fileSummaryQuery)(graph, resolved);
|
|
61
|
+
if (values.json) {
|
|
62
|
+
(0, format_1.printJson)((0, format_1.envelope)('explore.file', { path: resolved }, graph, result));
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
if (!result.found) {
|
|
66
|
+
(0, format_1.printMarkdown)((0, format_1.markdownHeader)('File', resolved, graph), `File \`${resolved}\` is not in the graph. Common reasons:\n` +
|
|
67
|
+
`- File doesn't exist (typo in path?)\n` +
|
|
68
|
+
`- Excluded by .dxkit-ignore / minified-detection / unsupported extension\n` +
|
|
69
|
+
`- Pack for this file's language isn't active in the project`);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const symbolRows = result.symbols.map((s) => ({
|
|
73
|
+
Kind: s.kind,
|
|
74
|
+
Symbol: s.label,
|
|
75
|
+
Line: s.line ?? '',
|
|
76
|
+
Exported: s.exported === undefined ? '?' : s.exported ? '✓' : '·',
|
|
77
|
+
'Calls in': s.callsIn,
|
|
78
|
+
'Calls out': s.callsOut,
|
|
79
|
+
}));
|
|
80
|
+
const symbolHeaders = ['Kind', 'Symbol', 'Line', 'Exported', 'Calls in', 'Calls out'];
|
|
81
|
+
const callerRows = result.callerFiles
|
|
82
|
+
.slice(0, 20)
|
|
83
|
+
.map((c) => ({ File: c.sourceFile, Calls: c.count }));
|
|
84
|
+
const calleeRows = result.calleeFiles
|
|
85
|
+
.slice(0, 20)
|
|
86
|
+
.map((c) => ({ File: c.sourceFile, Calls: c.count }));
|
|
87
|
+
const sections = [];
|
|
88
|
+
sections.push((0, format_1.markdownHeader)('File', resolved, graph));
|
|
89
|
+
// Community + summary line
|
|
90
|
+
const summary = [];
|
|
91
|
+
if (result.communityId !== undefined) {
|
|
92
|
+
const dir = result.communityLabel || '—';
|
|
93
|
+
const pack = result.communityPack || '—';
|
|
94
|
+
summary.push(`**Community**: ${result.communityId} (${dir}, ${pack})`);
|
|
95
|
+
}
|
|
96
|
+
const kindCounts = {};
|
|
97
|
+
for (const s of result.symbols)
|
|
98
|
+
kindCounts[s.kind] = (kindCounts[s.kind] ?? 0) + 1;
|
|
99
|
+
const symBreakdown = Object.entries(kindCounts)
|
|
100
|
+
.map(([k, c]) => `${c} ${k}${c === 1 ? '' : 's'}`)
|
|
101
|
+
.join(', ');
|
|
102
|
+
if (symBreakdown)
|
|
103
|
+
summary.push(`**Symbols**: ${symBreakdown}`);
|
|
104
|
+
const exportedSymbols = result.symbols.filter((s) => s.exported === true);
|
|
105
|
+
if (exportedSymbols.length > 0) {
|
|
106
|
+
summary.push(`**Exported**: ${exportedSymbols
|
|
107
|
+
.map((s) => s.label)
|
|
108
|
+
.slice(0, 8)
|
|
109
|
+
.join(', ')}${exportedSymbols.length > 8 ? ` (+${exportedSymbols.length - 8} more)` : ''}`);
|
|
110
|
+
}
|
|
111
|
+
if (summary.length > 0)
|
|
112
|
+
sections.push(summary.join('\n'));
|
|
113
|
+
if (symbolRows.length > 0) {
|
|
114
|
+
sections.push('### Symbols defined here');
|
|
115
|
+
sections.push((0, format_1.markdownTable)(symbolHeaders, symbolRows));
|
|
116
|
+
}
|
|
117
|
+
if (callerRows.length > 0) {
|
|
118
|
+
sections.push(`### Callers (${result.callerFiles.length} file${result.callerFiles.length === 1 ? '' : 's'})`);
|
|
119
|
+
sections.push((0, format_1.markdownTable)(['File', 'Calls'], callerRows));
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
sections.push('### Callers\n\nNo other files call into this file. Either it is a leaf module (entry point, top-level CLI handler) or its consumers are outside the graphify-extracted set.');
|
|
123
|
+
}
|
|
124
|
+
if (calleeRows.length > 0) {
|
|
125
|
+
sections.push(`### Callees (${result.calleeFiles.length} file${result.calleeFiles.length === 1 ? '' : 's'})`);
|
|
126
|
+
sections.push((0, format_1.markdownTable)(['File', 'Calls'], calleeRows));
|
|
127
|
+
}
|
|
128
|
+
if (result.importsOut.length > 0) {
|
|
129
|
+
sections.push(`### Imports out (${result.importsOut.length} file${result.importsOut.length === 1 ? '' : 's'})`);
|
|
130
|
+
sections.push(result.importsOut.map((i) => `- ${i.sourceFile}`).join('\n'));
|
|
131
|
+
}
|
|
132
|
+
if (result.importsIn.length > 0) {
|
|
133
|
+
sections.push(`### Imports in (${result.importsIn.length} file${result.importsIn.length === 1 ? '' : 's'})`);
|
|
134
|
+
sections.push(result.importsIn.map((i) => `- ${i.sourceFile}`).join('\n'));
|
|
135
|
+
}
|
|
136
|
+
sections.push((0, format_1.markdownFooter)('Drill into a caller: `vyuh-dxkit explore file <path>`.'));
|
|
137
|
+
(0, format_1.printMarkdown)(...sections);
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=file.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file.js","sourceRoot":"","sources":["../../../src/explore/cli/file.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `vyuh-dxkit explore hot-files` — files most depended on.
|
|
3
|
+
*
|
|
4
|
+
* Pure pipeline: parse args → call hotFilesQuery → format output.
|
|
5
|
+
* No graph traversal in here (CLAUDE.md Rule 12 enforces);
|
|
6
|
+
* everything goes through src/explore/queries.ts.
|
|
7
|
+
*/
|
|
8
|
+
import type { Graph } from '../types';
|
|
9
|
+
import type { ExploreCliValues } from '../../explore-cli';
|
|
10
|
+
export declare function runHotFiles(graph: Graph, _positionals: ReadonlyArray<string>, values: ExploreCliValues): void;
|
|
11
|
+
//# sourceMappingURL=hot-files.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hot-files.d.ts","sourceRoot":"","sources":["../../../src/explore/cli/hot-files.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAWH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAI1D,wBAAgB,WAAW,CACzB,KAAK,EAAE,KAAK,EACZ,YAAY,EAAE,aAAa,CAAC,MAAM,CAAC,EACnC,MAAM,EAAE,gBAAgB,GACvB,IAAI,CAqCN"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* `vyuh-dxkit explore hot-files` — files most depended on.
|
|
4
|
+
*
|
|
5
|
+
* Pure pipeline: parse args → call hotFilesQuery → format output.
|
|
6
|
+
* No graph traversal in here (CLAUDE.md Rule 12 enforces);
|
|
7
|
+
* everything goes through src/explore/queries.ts.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.runHotFiles = runHotFiles;
|
|
11
|
+
const queries_1 = require("../queries");
|
|
12
|
+
const format_1 = require("../format");
|
|
13
|
+
const DEFAULT_LIMIT = 20;
|
|
14
|
+
function runHotFiles(graph, _positionals, values) {
|
|
15
|
+
const limit = parseLimit(values.limit, DEFAULT_LIMIT);
|
|
16
|
+
const results = (0, queries_1.hotFilesQuery)(graph, limit);
|
|
17
|
+
if (values.json) {
|
|
18
|
+
(0, format_1.printJson)((0, format_1.envelope)('explore.hot-files', { limit }, graph, results));
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
// Markdown: header, table, footer hint.
|
|
22
|
+
const rows = results.map((r) => ({
|
|
23
|
+
Path: r.sourceFile,
|
|
24
|
+
'Calls in': r.callsIn,
|
|
25
|
+
'Imports in': r.importsIn,
|
|
26
|
+
'Calls out': r.callsOut,
|
|
27
|
+
Community: r.communityLabel
|
|
28
|
+
? `${r.communityId} (${r.communityLabel})`
|
|
29
|
+
: r.communityId !== undefined
|
|
30
|
+
? String(r.communityId)
|
|
31
|
+
: '',
|
|
32
|
+
}));
|
|
33
|
+
const headers = ['Path', 'Calls in', 'Imports in', 'Calls out', 'Community'];
|
|
34
|
+
if (results.length === 0) {
|
|
35
|
+
(0, format_1.printMarkdown)((0, format_1.markdownHeader)('Hot files', "what's central?", graph), 'No files found in the graph. Either the repo has no inbound call edges, or the graph artifact is empty.');
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
(0, format_1.printMarkdown)((0, format_1.markdownHeader)('Hot files', "what's central?", graph), (0, format_1.markdownTable)(headers, rows), explainResults(results), (0, format_1.markdownFooter)('Drill into one: `vyuh-dxkit explore file <path>`.'));
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* One-line interpretation hint below the table. A file with high
|
|
42
|
+
* "calls in" + low "calls out" is foundational infrastructure;
|
|
43
|
+
* inverting that signals a coordinator / orchestrator.
|
|
44
|
+
*/
|
|
45
|
+
function explainResults(results) {
|
|
46
|
+
if (results.length === 0)
|
|
47
|
+
return '';
|
|
48
|
+
const top = results[0];
|
|
49
|
+
const ratio = top.callsOut > 0 ? top.callsIn / top.callsOut : top.callsIn;
|
|
50
|
+
if (ratio >= 3) {
|
|
51
|
+
return `A file with high "calls in" + low "calls out" is foundational infrastructure. \`${top.sourceFile}\` looks like one.`;
|
|
52
|
+
}
|
|
53
|
+
return 'A file with high "calls in" + low "calls out" is foundational infrastructure.';
|
|
54
|
+
}
|
|
55
|
+
function parseLimit(raw, defaultValue) {
|
|
56
|
+
if (!raw)
|
|
57
|
+
return defaultValue;
|
|
58
|
+
const n = parseInt(raw, 10);
|
|
59
|
+
if (isNaN(n) || n < 1)
|
|
60
|
+
return defaultValue;
|
|
61
|
+
return Math.min(n, 1000); // sanity cap
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=hot-files.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hot-files.js","sourceRoot":"","sources":["../../../src/explore/cli/hot-files.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;AAgBH,kCAyCC;AAvDD,wCAA+D;AAC/D,sCAOmB;AAInB,MAAM,aAAa,GAAG,EAAE,CAAC;AAEzB,SAAgB,WAAW,CACzB,KAAY,EACZ,YAAmC,EACnC,MAAwB;IAExB,MAAM,KAAK,GAAG,UAAU,CAAC,MAAM,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;IACtD,MAAM,OAAO,GAAG,IAAA,uBAAa,EAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAE5C,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;QAChB,IAAA,kBAAS,EAAC,IAAA,iBAAQ,EAAC,mBAAmB,EAAE,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;QACpE,OAAO;IACT,CAAC;IAED,wCAAwC;IACxC,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC/B,IAAI,EAAE,CAAC,CAAC,UAAU;QAClB,UAAU,EAAE,CAAC,CAAC,OAAO;QACrB,YAAY,EAAE,CAAC,CAAC,SAAS;QACzB,WAAW,EAAE,CAAC,CAAC,QAAQ;QACvB,SAAS,EAAE,CAAC,CAAC,cAAc;YACzB,CAAC,CAAC,GAAG,CAAC,CAAC,WAAW,KAAK,CAAC,CAAC,cAAc,GAAG;YAC1C,CAAC,CAAC,CAAC,CAAC,WAAW,KAAK,SAAS;gBAC3B,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC;gBACvB,CAAC,CAAC,EAAE;KACT,CAAC,CAAC,CAAC;IACJ,MAAM,OAAO,GAAG,CAAC,MAAM,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,CAAU,CAAC;IAEtF,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,IAAA,sBAAa,EACX,IAAA,uBAAc,EAAC,WAAW,EAAE,iBAAiB,EAAE,KAAK,CAAC,EACrD,yGAAyG,CAC1G,CAAC;QACF,OAAO;IACT,CAAC;IAED,IAAA,sBAAa,EACX,IAAA,uBAAc,EAAC,WAAW,EAAE,iBAAiB,EAAE,KAAK,CAAC,EACrD,IAAA,sBAAa,EAAC,OAAO,EAAE,IAAI,CAAC,EAC5B,cAAc,CAAC,OAAO,CAAC,EACvB,IAAA,uBAAc,EAAC,mDAAmD,CAAC,CACpE,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAS,cAAc,CAAC,OAAwB;IAC9C,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACpC,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACvB,MAAM,KAAK,GAAG,GAAG,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC;IAC1E,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;QACf,OAAO,mFAAmF,GAAG,CAAC,UAAU,oBAAoB,CAAC;IAC/H,CAAC;IACD,OAAO,+EAA+E,CAAC;AACzF,CAAC;AAED,SAAS,UAAU,CAAC,GAAuB,EAAE,YAAoB;IAC/D,IAAI,CAAC,GAAG;QAAE,OAAO,YAAY,CAAC;IAC9B,MAAM,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IAC5B,IAAI,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,YAAY,CAAC;IAC3C,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,aAAa;AACzC,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `vyuh-dxkit context-hook` — the Claude Code PreToolUse hook that
|
|
3
|
+
* delivers the token-reduction win passively. Wired into a scaffolded
|
|
4
|
+
* repo's `.claude/settings.json` with a `Grep|Glob` matcher: when an
|
|
5
|
+
* agent is about to search the codebase, this hook injects a slim
|
|
6
|
+
* structural map as `additionalContext` so the agent needs fewer
|
|
7
|
+
* follow-up whole-file reads.
|
|
8
|
+
*
|
|
9
|
+
* THE CONTRACT IS FAIL-OPEN + ADDITIVE. This hook can only ever ADD
|
|
10
|
+
* context; it never blocks the tool, never replaces grep output, and
|
|
11
|
+
* stays a silent no-op (exit 0, no stdout) on ANY problem — missing
|
|
12
|
+
* graph.json, parse error, no keyword match, unreadable stdin. So
|
|
13
|
+
* Claude Code behaves exactly as it does today whenever the graph is
|
|
14
|
+
* absent or unhelpful; the hook is pure upside.
|
|
15
|
+
*
|
|
16
|
+
* Claude Code passes the tool call as JSON on stdin
|
|
17
|
+
* (`{ tool_name, tool_input: { pattern, ... }, ... }`) and reads a
|
|
18
|
+
* JSON object on stdout with `hookSpecificOutput.additionalContext`.
|
|
19
|
+
*/
|
|
20
|
+
import { type ContextResult } from './queries';
|
|
21
|
+
import type { Graph } from './types';
|
|
22
|
+
/**
|
|
23
|
+
* Entry point for `case 'context-hook'`. Reads stdin, runs the query,
|
|
24
|
+
* writes the hook output. Wrapped so nothing it does can fail the
|
|
25
|
+
* tool call: every failure path resolves to a silent no-op.
|
|
26
|
+
*/
|
|
27
|
+
export declare function runContextHook(cwd: string): Promise<void>;
|
|
28
|
+
/**
|
|
29
|
+
* Extract the search keyword from the PreToolUse payload. Both Grep
|
|
30
|
+
* and Glob carry it on `tool_input.pattern`. Returns undefined for
|
|
31
|
+
* anything we can't confidently read (→ no-op upstream).
|
|
32
|
+
*/
|
|
33
|
+
export declare function extractPattern(rawStdin: string): string | undefined;
|
|
34
|
+
/**
|
|
35
|
+
* Compact `additionalContext` body. Terser than the CLI's markdown
|
|
36
|
+
* (the hook pays this cost on every grep): an anchor line, blast
|
|
37
|
+
* radius, and the top symbols grouped by their leading community.
|
|
38
|
+
* Leads with a one-line provenance + best-effort caveat so the agent
|
|
39
|
+
* calibrates trust.
|
|
40
|
+
*/
|
|
41
|
+
export declare function formatHookContext(result: ContextResult, graph: Graph): string;
|
|
42
|
+
//# sourceMappingURL=context-hook.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-hook.d.ts","sourceRoot":"","sources":["../../src/explore/context-hook.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAgB,KAAK,aAAa,EAAE,MAAM,WAAW,CAAC;AAE7D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAKrC;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA0B/D;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAcnE;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,KAAK,GAAG,MAAM,CAiC7E"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* `vyuh-dxkit context-hook` — the Claude Code PreToolUse hook that
|
|
4
|
+
* delivers the token-reduction win passively. Wired into a scaffolded
|
|
5
|
+
* repo's `.claude/settings.json` with a `Grep|Glob` matcher: when an
|
|
6
|
+
* agent is about to search the codebase, this hook injects a slim
|
|
7
|
+
* structural map as `additionalContext` so the agent needs fewer
|
|
8
|
+
* follow-up whole-file reads.
|
|
9
|
+
*
|
|
10
|
+
* THE CONTRACT IS FAIL-OPEN + ADDITIVE. This hook can only ever ADD
|
|
11
|
+
* context; it never blocks the tool, never replaces grep output, and
|
|
12
|
+
* stays a silent no-op (exit 0, no stdout) on ANY problem — missing
|
|
13
|
+
* graph.json, parse error, no keyword match, unreadable stdin. So
|
|
14
|
+
* Claude Code behaves exactly as it does today whenever the graph is
|
|
15
|
+
* absent or unhelpful; the hook is pure upside.
|
|
16
|
+
*
|
|
17
|
+
* Claude Code passes the tool call as JSON on stdin
|
|
18
|
+
* (`{ tool_name, tool_input: { pattern, ... }, ... }`) and reads a
|
|
19
|
+
* JSON object on stdout with `hookSpecificOutput.additionalContext`.
|
|
20
|
+
*/
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
exports.runContextHook = runContextHook;
|
|
23
|
+
exports.extractPattern = extractPattern;
|
|
24
|
+
exports.formatHookContext = formatHookContext;
|
|
25
|
+
const queries_1 = require("./queries");
|
|
26
|
+
const load_1 = require("./load");
|
|
27
|
+
/** Stingier than the manual CLI's 2000 — the hook fires on every grep. */
|
|
28
|
+
const HOOK_BUDGET = 1500;
|
|
29
|
+
/**
|
|
30
|
+
* Entry point for `case 'context-hook'`. Reads stdin, runs the query,
|
|
31
|
+
* writes the hook output. Wrapped so nothing it does can fail the
|
|
32
|
+
* tool call: every failure path resolves to a silent no-op.
|
|
33
|
+
*/
|
|
34
|
+
async function runContextHook(cwd) {
|
|
35
|
+
try {
|
|
36
|
+
const raw = await readStdin();
|
|
37
|
+
if (!raw.trim())
|
|
38
|
+
return;
|
|
39
|
+
const pattern = extractPattern(raw);
|
|
40
|
+
if (!pattern)
|
|
41
|
+
return;
|
|
42
|
+
const graph = (0, load_1.tryLoadGraph)(cwd);
|
|
43
|
+
if (!graph)
|
|
44
|
+
return;
|
|
45
|
+
const result = (0, queries_1.contextQuery)(graph, pattern, { budget: HOOK_BUDGET, substring: true });
|
|
46
|
+
if (!result.matched || result.selection.length === 0)
|
|
47
|
+
return;
|
|
48
|
+
const additionalContext = formatHookContext(result, graph);
|
|
49
|
+
process.stdout.write(JSON.stringify({
|
|
50
|
+
hookSpecificOutput: {
|
|
51
|
+
hookEventName: 'PreToolUse',
|
|
52
|
+
additionalContext,
|
|
53
|
+
},
|
|
54
|
+
}));
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
// Fail-open: errors produce no output; the tool proceeds normally.
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Extract the search keyword from the PreToolUse payload. Both Grep
|
|
62
|
+
* and Glob carry it on `tool_input.pattern`. Returns undefined for
|
|
63
|
+
* anything we can't confidently read (→ no-op upstream).
|
|
64
|
+
*/
|
|
65
|
+
function extractPattern(rawStdin) {
|
|
66
|
+
let parsed;
|
|
67
|
+
try {
|
|
68
|
+
parsed = JSON.parse(rawStdin);
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
if (!parsed || typeof parsed !== 'object')
|
|
74
|
+
return undefined;
|
|
75
|
+
const toolInput = parsed.tool_input;
|
|
76
|
+
if (!toolInput || typeof toolInput !== 'object')
|
|
77
|
+
return undefined;
|
|
78
|
+
const pattern = toolInput.pattern;
|
|
79
|
+
if (typeof pattern !== 'string')
|
|
80
|
+
return undefined;
|
|
81
|
+
const trimmed = pattern.trim();
|
|
82
|
+
return trimmed.length > 0 ? trimmed : undefined;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Compact `additionalContext` body. Terser than the CLI's markdown
|
|
86
|
+
* (the hook pays this cost on every grep): an anchor line, blast
|
|
87
|
+
* radius, and the top symbols grouped by their leading community.
|
|
88
|
+
* Leads with a one-line provenance + best-effort caveat so the agent
|
|
89
|
+
* calibrates trust.
|
|
90
|
+
*/
|
|
91
|
+
function formatHookContext(result, graph) {
|
|
92
|
+
const lines = [];
|
|
93
|
+
lines.push(`dxkit graph context for \`${result.query}\` (from .dxkit/reports/graph.json, generated ${graph.meta.generatedAt.slice(0, 10)} — structural hint, grep results remain authoritative):`);
|
|
94
|
+
if (result.anchor) {
|
|
95
|
+
const a = result.anchor;
|
|
96
|
+
const where = a.line ? `${a.sourceFile}:${a.line}` : a.sourceFile;
|
|
97
|
+
lines.push(`- Start here: \`${a.symbol}\` (${where}), called from ${a.calledFrom} place(s).`);
|
|
98
|
+
}
|
|
99
|
+
if (result.blastRadius.callers > 0) {
|
|
100
|
+
lines.push(`- Blast radius: ${result.blastRadius.callers} caller(s) across ${result.blastRadius.callerFiles} file(s).`);
|
|
101
|
+
}
|
|
102
|
+
// Top symbols overall (seeds first, then by in-degree), capped tight.
|
|
103
|
+
const top = [...result.selection]
|
|
104
|
+
.sort((a, b) => a.hop - b.hop || b.callsIn - a.callsIn)
|
|
105
|
+
.slice(0, 10);
|
|
106
|
+
if (top.length > 0) {
|
|
107
|
+
lines.push('- Relevant symbols:');
|
|
108
|
+
for (const s of top) {
|
|
109
|
+
const where = s.line ? `${s.sourceFile}:${s.line}` : s.sourceFile;
|
|
110
|
+
lines.push(` ${s.symbol} (${where})`);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (result.truncated) {
|
|
114
|
+
lines.push(`- (+${result.omittedCount} more symbols in the wider neighborhood)`);
|
|
115
|
+
}
|
|
116
|
+
return lines.join('\n');
|
|
117
|
+
}
|
|
118
|
+
/** Read all of stdin as a string. Resolves '' if stdin is a TTY/empty. */
|
|
119
|
+
function readStdin() {
|
|
120
|
+
return new Promise((resolve) => {
|
|
121
|
+
if (process.stdin.isTTY) {
|
|
122
|
+
resolve('');
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
const chunks = [];
|
|
126
|
+
process.stdin.on('data', (c) => chunks.push(Buffer.from(c)));
|
|
127
|
+
process.stdin.on('end', () => resolve(Buffer.concat(chunks).toString('utf-8')));
|
|
128
|
+
process.stdin.on('error', () => resolve(''));
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=context-hook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-hook.js","sourceRoot":"","sources":["../../src/explore/context-hook.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Finding-enrichment adapter — attaches graph context (module
|
|
3
|
+
* membership + blast radius + enclosing symbol) to analyzer findings
|
|
4
|
+
* that carry a `file` (+ optional `line`). Consumed by the detailed
|
|
5
|
+
* report builders for the `vuln` / `test-gaps` / `quality` commands
|
|
6
|
+
* when the user passes `--graph-context`.
|
|
7
|
+
*
|
|
8
|
+
* Per CLAUDE.md Rule 12 this is the only layer (alongside the context
|
|
9
|
+
* hook + dashboard adapter) that loads the graph for finding
|
|
10
|
+
* enrichment; analyzers receive the pre-built `DetailedGraphContext`
|
|
11
|
+
* and never touch graph.json themselves. All graph math stays in
|
|
12
|
+
* `queries.ts:findingContextQuery`.
|
|
13
|
+
*
|
|
14
|
+
* THE CONTRACT IS FAIL-OPEN + ADDITIVE, like the context hook: a
|
|
15
|
+
* missing / corrupt / stale graph degrades to `undefined` (no
|
|
16
|
+
* enrichment), never an error. Findings render exactly as they do
|
|
17
|
+
* today whenever the graph is absent.
|
|
18
|
+
*/
|
|
19
|
+
import { type FindingContext } from './queries';
|
|
20
|
+
/** A finding's location — the enrichment key. `line` optional (file-level findings). */
|
|
21
|
+
export interface FindingLocation {
|
|
22
|
+
file: string;
|
|
23
|
+
line?: number;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* The enrichment payload stored on a detailed report. `generatedAt` +
|
|
27
|
+
* `truncated` carry the graph.json provenance so a reader can detect a
|
|
28
|
+
* stale enrichment (the graph predates the analyzed commit) without
|
|
29
|
+
* re-loading the artifact. `contexts` is keyed by `locationKey` and
|
|
30
|
+
* holds only `found: true` entries — files absent from the graph
|
|
31
|
+
* produce no key (the renderer treats a missing key as "no context").
|
|
32
|
+
*/
|
|
33
|
+
export interface DetailedGraphContext {
|
|
34
|
+
generatedAt: string;
|
|
35
|
+
truncated: boolean;
|
|
36
|
+
contexts: Record<string, FindingContext>;
|
|
37
|
+
}
|
|
38
|
+
export interface BuildFindingContextOpts {
|
|
39
|
+
/** Budget cap: only the first N unique locations are enriched (bloat guard). */
|
|
40
|
+
maxFindings?: number;
|
|
41
|
+
/** Sample size of caller files surfaced per finding. */
|
|
42
|
+
topCallerFiles?: number;
|
|
43
|
+
}
|
|
44
|
+
/** Stable lookup key for a finding location. */
|
|
45
|
+
export declare function locationKey(file: string, line?: number): string;
|
|
46
|
+
/**
|
|
47
|
+
* Build per-finding graph context for a list of finding locations.
|
|
48
|
+
* Fail-open: returns `undefined` when the graph can't be loaded.
|
|
49
|
+
*
|
|
50
|
+
* Dedupes identical locations (same file:line surfaced by multiple
|
|
51
|
+
* tools) and budget-caps the work at `maxFindings` unique locations.
|
|
52
|
+
* Only `found: true` contexts are stored — a finding in a file the
|
|
53
|
+
* graph never parsed contributes no key, keeping the payload lean on
|
|
54
|
+
* repos where graphify covers only part of the tree.
|
|
55
|
+
*/
|
|
56
|
+
export declare function buildFindingContextMap(cwd: string, locations: ReadonlyArray<FindingLocation>, opts?: BuildFindingContextOpts): DetailedGraphContext | undefined;
|
|
57
|
+
/**
|
|
58
|
+
* Compact one-cell rendering for a markdown table: `role · N caller
|
|
59
|
+
* files`. Returns `—` when there's no context for the location (file
|
|
60
|
+
* not in the graph). Used by the detailed report renderers.
|
|
61
|
+
*/
|
|
62
|
+
export declare function formatGraphContextCell(ctx: FindingContext | undefined): string;
|
|
63
|
+
/**
|
|
64
|
+
* Provenance + honesty line printed above an enriched section so the
|
|
65
|
+
* reader knows the context is a structural hint tied to a specific
|
|
66
|
+
* graph snapshot (and that graphify can conflate same-name symbols).
|
|
67
|
+
*/
|
|
68
|
+
export declare function graphContextProvenanceLine(gc: DetailedGraphContext): string;
|
|
69
|
+
//# sourceMappingURL=finding-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"finding-context.d.ts","sourceRoot":"","sources":["../../src/explore/finding-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,EAAuB,KAAK,cAAc,EAAE,MAAM,WAAW,CAAC;AAGrE,wFAAwF;AACxF,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;CAC1C;AAED,MAAM,WAAW,uBAAuB;IACtC,gFAAgF;IAChF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wDAAwD;IACxD,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,gDAAgD;AAChD,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAE/D;AAED;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,aAAa,CAAC,eAAe,CAAC,EACzC,IAAI,GAAE,uBAA4B,GACjC,oBAAoB,GAAG,SAAS,CA4BlC;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,cAAc,GAAG,SAAS,GAAG,MAAM,CAY9E;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,EAAE,EAAE,oBAAoB,GAAG,MAAM,CAI3E"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Finding-enrichment adapter — attaches graph context (module
|
|
4
|
+
* membership + blast radius + enclosing symbol) to analyzer findings
|
|
5
|
+
* that carry a `file` (+ optional `line`). Consumed by the detailed
|
|
6
|
+
* report builders for the `vuln` / `test-gaps` / `quality` commands
|
|
7
|
+
* when the user passes `--graph-context`.
|
|
8
|
+
*
|
|
9
|
+
* Per CLAUDE.md Rule 12 this is the only layer (alongside the context
|
|
10
|
+
* hook + dashboard adapter) that loads the graph for finding
|
|
11
|
+
* enrichment; analyzers receive the pre-built `DetailedGraphContext`
|
|
12
|
+
* and never touch graph.json themselves. All graph math stays in
|
|
13
|
+
* `queries.ts:findingContextQuery`.
|
|
14
|
+
*
|
|
15
|
+
* THE CONTRACT IS FAIL-OPEN + ADDITIVE, like the context hook: a
|
|
16
|
+
* missing / corrupt / stale graph degrades to `undefined` (no
|
|
17
|
+
* enrichment), never an error. Findings render exactly as they do
|
|
18
|
+
* today whenever the graph is absent.
|
|
19
|
+
*/
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
exports.locationKey = locationKey;
|
|
22
|
+
exports.buildFindingContextMap = buildFindingContextMap;
|
|
23
|
+
exports.formatGraphContextCell = formatGraphContextCell;
|
|
24
|
+
exports.graphContextProvenanceLine = graphContextProvenanceLine;
|
|
25
|
+
const load_1 = require("./load");
|
|
26
|
+
const queries_1 = require("./queries");
|
|
27
|
+
const languages_1 = require("../languages");
|
|
28
|
+
/** Stable lookup key for a finding location. */
|
|
29
|
+
function locationKey(file, line) {
|
|
30
|
+
return typeof line === 'number' ? `${file}:${line}` : file;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Build per-finding graph context for a list of finding locations.
|
|
34
|
+
* Fail-open: returns `undefined` when the graph can't be loaded.
|
|
35
|
+
*
|
|
36
|
+
* Dedupes identical locations (same file:line surfaced by multiple
|
|
37
|
+
* tools) and budget-caps the work at `maxFindings` unique locations.
|
|
38
|
+
* Only `found: true` contexts are stored — a finding in a file the
|
|
39
|
+
* graph never parsed contributes no key, keeping the payload lean on
|
|
40
|
+
* repos where graphify covers only part of the tree.
|
|
41
|
+
*/
|
|
42
|
+
function buildFindingContextMap(cwd, locations, opts = {}) {
|
|
43
|
+
const graph = (0, load_1.tryLoadGraph)(cwd);
|
|
44
|
+
if (!graph)
|
|
45
|
+
return undefined;
|
|
46
|
+
const max = opts.maxFindings ?? 200;
|
|
47
|
+
const contexts = {};
|
|
48
|
+
let enriched = 0;
|
|
49
|
+
for (const loc of locations) {
|
|
50
|
+
if (enriched >= max)
|
|
51
|
+
break;
|
|
52
|
+
const key = locationKey(loc.file, loc.line);
|
|
53
|
+
if (key in contexts)
|
|
54
|
+
continue;
|
|
55
|
+
const ctx = (0, queries_1.findingContextQuery)(graph, loc.file, loc.line, {
|
|
56
|
+
topCallerFiles: opts.topCallerFiles,
|
|
57
|
+
});
|
|
58
|
+
enriched++;
|
|
59
|
+
if (!ctx.found)
|
|
60
|
+
continue;
|
|
61
|
+
// Stamp the file's call-graph reliability (Rule 6: the fact comes
|
|
62
|
+
// from the language pack, not a hardcoded table here). Only record
|
|
63
|
+
// the non-default values to keep the payload lean — absent ⇒ 'full'.
|
|
64
|
+
const rel = (0, languages_1.languageForFile)(loc.file)?.callGraphReliability;
|
|
65
|
+
contexts[key] = rel && rel !== 'full' ? { ...ctx, callGraphReliability: rel } : ctx;
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
generatedAt: graph.meta.generatedAt,
|
|
69
|
+
truncated: graph.meta.truncated,
|
|
70
|
+
contexts,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Compact one-cell rendering for a markdown table: `role · N caller
|
|
75
|
+
* files`. Returns `—` when there's no context for the location (file
|
|
76
|
+
* not in the graph). Used by the detailed report renderers.
|
|
77
|
+
*/
|
|
78
|
+
function formatGraphContextCell(ctx) {
|
|
79
|
+
if (!ctx || !ctx.found)
|
|
80
|
+
return '—';
|
|
81
|
+
const role = ctx.community?.role ?? 'unclustered';
|
|
82
|
+
// For languages graphify can't resolve call edges for (C#), the
|
|
83
|
+
// caller count is untrustworthy — suppress it rather than print a
|
|
84
|
+
// misleading "0 caller files" (which a fixing agent could read as
|
|
85
|
+
// "safe to change"). The module/role label is still reliable.
|
|
86
|
+
if (ctx.callGraphReliability === 'unreliable') {
|
|
87
|
+
return `${role} · blast radius n/a (call graph)`;
|
|
88
|
+
}
|
|
89
|
+
const n = ctx.blastRadius.callerFiles;
|
|
90
|
+
return `${role} · ${n} caller file${n === 1 ? '' : 's'}`;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Provenance + honesty line printed above an enriched section so the
|
|
94
|
+
* reader knows the context is a structural hint tied to a specific
|
|
95
|
+
* graph snapshot (and that graphify can conflate same-name symbols).
|
|
96
|
+
*/
|
|
97
|
+
function graphContextProvenanceLine(gc) {
|
|
98
|
+
const date = gc.generatedAt.slice(0, 10);
|
|
99
|
+
const stale = gc.truncated ? ' (graph truncated — coverage partial)' : '';
|
|
100
|
+
return `_Graph context column from \`.dxkit/reports/graph.json\` (generated ${date}${stale}) — structural hint; blast radius is file-level, same-name symbols may conflate call edges, and it reads \`n/a\` for languages whose call graph graphify can't resolve (a blank is not "0 callers"/"safe to change")._`;
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=finding-context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"finding-context.js","sourceRoot":"","sources":["../../src/explore/finding-context.ts"],"names":[],"mappings":"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"}
|