@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.
Files changed (151) hide show
  1. package/CHANGELOG.md +54 -13
  2. package/README.md +208 -459
  3. package/dist/analyzers/bom/discovery.d.ts +3 -4
  4. package/dist/analyzers/bom/discovery.d.ts.map +1 -1
  5. package/dist/analyzers/bom/discovery.js +3 -4
  6. package/dist/analyzers/bom/discovery.js.map +1 -1
  7. package/dist/analyzers/bom/types.d.ts +1 -1
  8. package/dist/analyzers/dashboard/index.d.ts.map +1 -1
  9. package/dist/analyzers/dashboard/index.js +42 -5
  10. package/dist/analyzers/dashboard/index.js.map +1 -1
  11. package/dist/analyzers/quality/detailed.d.ts +8 -1
  12. package/dist/analyzers/quality/detailed.d.ts.map +1 -1
  13. package/dist/analyzers/quality/detailed.js +43 -10
  14. package/dist/analyzers/quality/detailed.js.map +1 -1
  15. package/dist/analyzers/security/detailed.d.ts +8 -1
  16. package/dist/analyzers/security/detailed.d.ts.map +1 -1
  17. package/dist/analyzers/security/detailed.js +14 -1
  18. package/dist/analyzers/security/detailed.js.map +1 -1
  19. package/dist/analyzers/tests/detailed.d.ts +8 -1
  20. package/dist/analyzers/tests/detailed.d.ts.map +1 -1
  21. package/dist/analyzers/tests/detailed.js +26 -7
  22. package/dist/analyzers/tests/detailed.js.map +1 -1
  23. package/dist/analyzers/tools/cloc.js +3 -3
  24. package/dist/analyzers/tools/cloc.js.map +1 -1
  25. package/dist/analyzers/tools/exclusions.d.ts +12 -12
  26. package/dist/analyzers/tools/exclusions.d.ts.map +1 -1
  27. package/dist/analyzers/tools/exclusions.js +27 -13
  28. package/dist/analyzers/tools/exclusions.js.map +1 -1
  29. package/dist/analyzers/tools/graphify.d.ts +39 -5
  30. package/dist/analyzers/tools/graphify.d.ts.map +1 -1
  31. package/dist/analyzers/tools/graphify.js +609 -45
  32. package/dist/analyzers/tools/graphify.js.map +1 -1
  33. package/dist/analyzers/tools/nuget-package-reference.d.ts +4 -4
  34. package/dist/analyzers/tools/nuget-package-reference.js +4 -4
  35. package/dist/analyzers/tools/osv-scanner-fix.d.ts +4 -5
  36. package/dist/analyzers/tools/osv-scanner-fix.d.ts.map +1 -1
  37. package/dist/analyzers/tools/osv-scanner-fix.js +4 -5
  38. package/dist/analyzers/tools/osv-scanner-fix.js.map +1 -1
  39. package/dist/analyzers/tools/parallel.d.ts.map +1 -1
  40. package/dist/analyzers/tools/parallel.js +7 -0
  41. package/dist/analyzers/tools/parallel.js.map +1 -1
  42. package/dist/analyzers/tools/vendored-advisor.d.ts.map +1 -1
  43. package/dist/analyzers/tools/vendored-advisor.js +3 -4
  44. package/dist/analyzers/tools/vendored-advisor.js.map +1 -1
  45. package/dist/analyzers/xlsx/licenses.d.ts +7 -7
  46. package/dist/analyzers/xlsx/licenses.js +7 -7
  47. package/dist/cli.d.ts.map +1 -1
  48. package/dist/cli.js +80 -3
  49. package/dist/cli.js.map +1 -1
  50. package/dist/dashboard/graph-adapter.d.ts +151 -0
  51. package/dist/dashboard/graph-adapter.d.ts.map +1 -0
  52. package/dist/dashboard/graph-adapter.js +415 -0
  53. package/dist/dashboard/graph-adapter.js.map +1 -0
  54. package/dist/dashboard/graph-tab.d.ts +109 -0
  55. package/dist/dashboard/graph-tab.d.ts.map +1 -0
  56. package/dist/dashboard/graph-tab.js +297 -0
  57. package/dist/dashboard/graph-tab.js.map +1 -0
  58. package/dist/dashboard/vendor/vis-network.min.js +34 -0
  59. package/dist/explore/cli/api-surface.d.ts +12 -0
  60. package/dist/explore/cli/api-surface.d.ts.map +1 -0
  61. package/dist/explore/cli/api-surface.js +57 -0
  62. package/dist/explore/cli/api-surface.js.map +1 -0
  63. package/dist/explore/cli/communities.d.ts +10 -0
  64. package/dist/explore/cli/communities.d.ts.map +1 -0
  65. package/dist/explore/cli/communities.js +47 -0
  66. package/dist/explore/cli/communities.js.map +1 -0
  67. package/dist/explore/cli/context.d.ts +16 -0
  68. package/dist/explore/cli/context.d.ts.map +1 -0
  69. package/dist/explore/cli/context.js +118 -0
  70. package/dist/explore/cli/context.js.map +1 -0
  71. package/dist/explore/cli/entry-points.d.ts +12 -0
  72. package/dist/explore/cli/entry-points.d.ts.map +1 -0
  73. package/dist/explore/cli/entry-points.js +85 -0
  74. package/dist/explore/cli/entry-points.js.map +1 -0
  75. package/dist/explore/cli/feature.d.ts +16 -0
  76. package/dist/explore/cli/feature.d.ts.map +1 -0
  77. package/dist/explore/cli/feature.js +89 -0
  78. package/dist/explore/cli/feature.js.map +1 -0
  79. package/dist/explore/cli/file.d.ts +12 -0
  80. package/dist/explore/cli/file.d.ts.map +1 -0
  81. package/dist/explore/cli/file.js +139 -0
  82. package/dist/explore/cli/file.js.map +1 -0
  83. package/dist/explore/cli/hot-files.d.ts +11 -0
  84. package/dist/explore/cli/hot-files.d.ts.map +1 -0
  85. package/dist/explore/cli/hot-files.js +63 -0
  86. package/dist/explore/cli/hot-files.js.map +1 -0
  87. package/dist/explore/context-hook.d.ts +42 -0
  88. package/dist/explore/context-hook.d.ts.map +1 -0
  89. package/dist/explore/context-hook.js +131 -0
  90. package/dist/explore/context-hook.js.map +1 -0
  91. package/dist/explore/finding-context.d.ts +69 -0
  92. package/dist/explore/finding-context.d.ts.map +1 -0
  93. package/dist/explore/finding-context.js +102 -0
  94. package/dist/explore/finding-context.js.map +1 -0
  95. package/dist/explore/format.d.ts +64 -0
  96. package/dist/explore/format.d.ts.map +1 -0
  97. package/dist/explore/format.js +99 -0
  98. package/dist/explore/format.js.map +1 -0
  99. package/dist/explore/load.d.ts +50 -0
  100. package/dist/explore/load.d.ts.map +1 -0
  101. package/dist/explore/load.js +197 -0
  102. package/dist/explore/load.js.map +1 -0
  103. package/dist/explore/queries.d.ts +413 -0
  104. package/dist/explore/queries.d.ts.map +1 -0
  105. package/dist/explore/queries.js +855 -0
  106. package/dist/explore/queries.js.map +1 -0
  107. package/dist/explore/types.d.ts +130 -0
  108. package/dist/explore/types.d.ts.map +1 -0
  109. package/dist/explore/types.js +28 -0
  110. package/dist/explore/types.js.map +1 -0
  111. package/dist/explore-cli.d.ts +45 -0
  112. package/dist/explore-cli.d.ts.map +1 -0
  113. package/dist/explore-cli.js +213 -0
  114. package/dist/explore-cli.js.map +1 -0
  115. package/dist/generator.d.ts.map +1 -1
  116. package/dist/generator.js +19 -0
  117. package/dist/generator.js.map +1 -1
  118. package/dist/languages/csharp.d.ts.map +1 -1
  119. package/dist/languages/csharp.js +31 -11
  120. package/dist/languages/csharp.js.map +1 -1
  121. package/dist/languages/go.d.ts.map +1 -1
  122. package/dist/languages/go.js +4 -0
  123. package/dist/languages/go.js.map +1 -1
  124. package/dist/languages/index.d.ts +27 -0
  125. package/dist/languages/index.d.ts.map +1 -1
  126. package/dist/languages/index.js +35 -0
  127. package/dist/languages/index.js.map +1 -1
  128. package/dist/languages/java.d.ts.map +1 -1
  129. package/dist/languages/java.js +4 -0
  130. package/dist/languages/java.js.map +1 -1
  131. package/dist/languages/kotlin.d.ts.map +1 -1
  132. package/dist/languages/kotlin.js +4 -0
  133. package/dist/languages/kotlin.js.map +1 -1
  134. package/dist/languages/python.d.ts.map +1 -1
  135. package/dist/languages/python.js +4 -0
  136. package/dist/languages/python.js.map +1 -1
  137. package/dist/languages/ruby.d.ts.map +1 -1
  138. package/dist/languages/ruby.js +4 -0
  139. package/dist/languages/ruby.js.map +1 -1
  140. package/dist/languages/rust.d.ts.map +1 -1
  141. package/dist/languages/rust.js +4 -0
  142. package/dist/languages/rust.js.map +1 -1
  143. package/dist/languages/types.d.ts +54 -0
  144. package/dist/languages/types.d.ts.map +1 -1
  145. package/dist/languages/typescript.d.ts.map +1 -1
  146. package/dist/languages/typescript.js +5 -1
  147. package/dist/languages/typescript.js.map +1 -1
  148. package/package.json +2 -1
  149. package/templates/.claude/skills/dxkit-action/SKILL.md +21 -1
  150. package/templates/.claude/skills/dxkit-reports/SKILL.md +3 -1
  151. 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":";AAAA;;;;;;;GAOG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAeH,0BA0HC;AAvID,gDAAkC;AAClC,wCAA8C;AAC9C,sCAOmB;AAInB,SAAgB,OAAO,CACrB,KAAY,EACZ,WAAkC,EAClC,MAAwB,EACxB,GAAW;IAEX,MAAM,OAAO,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;IAC/B,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,8GAA8G,CAC/G,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,kEAAkE;IAClE,8DAA8D;IAC9D,oBAAoB;IACpB,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;QACvC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;QACjD,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAEhC,MAAM,MAAM,GAAG,IAAA,0BAAgB,EAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IAEjD,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;QAChB,IAAA,kBAAS,EAAC,IAAA,iBAAQ,EAAC,cAAc,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;QACvE,OAAO;IACT,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAClB,IAAA,sBAAa,EACX,IAAA,uBAAc,EAAC,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,EACvC,UAAU,QAAQ,2CAA2C;YAC3D,wCAAwC;YACxC,4EAA4E;YAC5E,6DAA6D,CAChE,CAAC;QACF,OAAO;IACT,CAAC;IAED,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC5C,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,MAAM,EAAE,CAAC,CAAC,KAAK;QACf,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,EAAE;QAClB,QAAQ,EAAE,CAAC,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG;QACjE,UAAU,EAAE,CAAC,CAAC,OAAO;QACrB,WAAW,EAAE,CAAC,CAAC,QAAQ;KACxB,CAAC,CAAC,CAAC;IACJ,MAAM,aAAa,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,CAAU,CAAC;IAE/F,MAAM,UAAU,GAAG,MAAM,CAAC,WAAW;SAClC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;SACZ,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IACxD,MAAM,UAAU,GAAG,MAAM,CAAC,WAAW;SAClC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;SACZ,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IAExD,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,QAAQ,CAAC,IAAI,CAAC,IAAA,uBAAc,EAAC,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC;IAEvD,2BAA2B;IAC3B,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,MAAM,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,MAAM,CAAC,cAAc,IAAI,GAAG,CAAC;QACzC,MAAM,IAAI,GAAG,MAAM,CAAC,aAAa,IAAI,GAAG,CAAC;QACzC,OAAO,CAAC,IAAI,CAAC,kBAAkB,MAAM,CAAC,WAAW,KAAK,GAAG,KAAK,IAAI,GAAG,CAAC,CAAC;IACzE,CAAC;IACD,MAAM,UAAU,GAA2B,EAAE,CAAC;IAC9C,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO;QAAE,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;IACnF,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC;SAC5C,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;SACjD,IAAI,CAAC,IAAI,CAAC,CAAC;IACd,IAAI,YAAY;QAAE,OAAO,CAAC,IAAI,CAAC,gBAAgB,YAAY,EAAE,CAAC,CAAC;IAC/D,MAAM,eAAe,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,IAAI,CAAC,CAAC;IAC1E,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,OAAO,CAAC,IAAI,CACV,iBAAiB,eAAe;aAC7B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;aACnB,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;aACX,IAAI,CAAC,IAAI,CAAC,GAAG,eAAe,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,eAAe,CAAC,MAAM,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,CAC7F,CAAC;IACJ,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;QAAE,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAE1D,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,QAAQ,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;QAC1C,QAAQ,CAAC,IAAI,CAAC,IAAA,sBAAa,EAAC,aAAa,EAAE,UAAU,CAAC,CAAC,CAAC;IAC1D,CAAC;IAED,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,QAAQ,CAAC,IAAI,CACX,gBAAgB,MAAM,CAAC,WAAW,CAAC,MAAM,QAAQ,MAAM,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,CAC/F,CAAC;QACF,QAAQ,CAAC,IAAI,CAAC,IAAA,sBAAa,EAAC,CAAC,MAAM,EAAE,OAAO,CAAU,EAAE,UAAU,CAAC,CAAC,CAAC;IACvE,CAAC;SAAM,CAAC;QACN,QAAQ,CAAC,IAAI,CACX,6KAA6K,CAC9K,CAAC;IACJ,CAAC;IAED,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,QAAQ,CAAC,IAAI,CACX,gBAAgB,MAAM,CAAC,WAAW,CAAC,MAAM,QAAQ,MAAM,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,CAC/F,CAAC;QACF,QAAQ,CAAC,IAAI,CAAC,IAAA,sBAAa,EAAC,CAAC,MAAM,EAAE,OAAO,CAAU,EAAE,UAAU,CAAC,CAAC,CAAC;IACvE,CAAC;IAED,IAAI,MAAM,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACjC,QAAQ,CAAC,IAAI,CACX,oBAAoB,MAAM,CAAC,UAAU,CAAC,MAAM,QAAQ,MAAM,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,CACjG,CAAC;QACF,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAC9E,CAAC;IACD,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChC,QAAQ,CAAC,IAAI,CACX,mBAAmB,MAAM,CAAC,SAAS,CAAC,MAAM,QAAQ,MAAM,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,CAC9F,CAAC;QACF,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAC7E,CAAC;IAED,QAAQ,CAAC,IAAI,CAAC,IAAA,uBAAc,EAAC,wDAAwD,CAAC,CAAC,CAAC;IAExF,IAAA,sBAAa,EAAC,GAAG,QAAQ,CAAC,CAAC;AAC7B,CAAC"}
@@ -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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"}