@vyuhlabs/dxkit 1.5.1 → 1.6.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 (257) hide show
  1. package/CHANGELOG.md +264 -0
  2. package/README.md +265 -352
  3. package/THIRD_PARTY_NOTICES.md +40 -0
  4. package/dist/analyzers/developer/detailed.d.ts +26 -0
  5. package/dist/analyzers/developer/detailed.d.ts.map +1 -0
  6. package/dist/analyzers/developer/detailed.js +193 -0
  7. package/dist/analyzers/developer/detailed.js.map +1 -0
  8. package/dist/analyzers/developer/gather.d.ts +11 -0
  9. package/dist/analyzers/developer/gather.d.ts.map +1 -0
  10. package/dist/analyzers/developer/gather.js +167 -0
  11. package/dist/analyzers/developer/gather.js.map +1 -0
  12. package/dist/analyzers/developer/index.d.ts +8 -0
  13. package/dist/analyzers/developer/index.d.ts.map +1 -0
  14. package/dist/analyzers/developer/index.js +168 -0
  15. package/dist/analyzers/developer/index.js.map +1 -0
  16. package/dist/analyzers/developer/types.d.ts +49 -0
  17. package/dist/analyzers/developer/types.d.ts.map +1 -0
  18. package/dist/analyzers/developer/types.js +6 -0
  19. package/dist/analyzers/developer/types.js.map +1 -0
  20. package/dist/analyzers/docs/shallow.d.ts +9 -0
  21. package/dist/analyzers/docs/shallow.d.ts.map +1 -0
  22. package/dist/analyzers/docs/shallow.js +8 -0
  23. package/dist/analyzers/docs/shallow.js.map +1 -0
  24. package/dist/analyzers/dx/shallow.d.ts +9 -0
  25. package/dist/analyzers/dx/shallow.d.ts.map +1 -0
  26. package/dist/analyzers/dx/shallow.js +8 -0
  27. package/dist/analyzers/dx/shallow.js.map +1 -0
  28. package/dist/analyzers/evidence.d.ts +36 -0
  29. package/dist/analyzers/evidence.d.ts.map +1 -0
  30. package/dist/analyzers/evidence.js +3 -0
  31. package/dist/analyzers/evidence.js.map +1 -0
  32. package/dist/analyzers/health/actions.d.ts +10 -0
  33. package/dist/analyzers/health/actions.d.ts.map +1 -0
  34. package/dist/analyzers/health/actions.js +284 -0
  35. package/dist/analyzers/health/actions.js.map +1 -0
  36. package/dist/analyzers/health/detailed.d.ts +26 -0
  37. package/dist/analyzers/health/detailed.d.ts.map +1 -0
  38. package/dist/analyzers/health/detailed.js +147 -0
  39. package/dist/analyzers/health/detailed.js.map +1 -0
  40. package/dist/analyzers/health.d.ts +22 -0
  41. package/dist/analyzers/health.d.ts.map +1 -0
  42. package/dist/analyzers/health.js +270 -0
  43. package/dist/analyzers/health.js.map +1 -0
  44. package/dist/analyzers/index.d.ts +3 -0
  45. package/dist/analyzers/index.d.ts.map +1 -0
  46. package/dist/analyzers/index.js +6 -0
  47. package/dist/analyzers/index.js.map +1 -0
  48. package/dist/analyzers/maintainability/shallow.d.ts +9 -0
  49. package/dist/analyzers/maintainability/shallow.d.ts.map +1 -0
  50. package/dist/analyzers/maintainability/shallow.js +8 -0
  51. package/dist/analyzers/maintainability/shallow.js.map +1 -0
  52. package/dist/analyzers/quality/actions.d.ts +5 -0
  53. package/dist/analyzers/quality/actions.d.ts.map +1 -0
  54. package/dist/analyzers/quality/actions.js +158 -0
  55. package/dist/analyzers/quality/actions.js.map +1 -0
  56. package/dist/analyzers/quality/detailed.d.ts +17 -0
  57. package/dist/analyzers/quality/detailed.d.ts.map +1 -0
  58. package/dist/analyzers/quality/detailed.js +122 -0
  59. package/dist/analyzers/quality/detailed.js.map +1 -0
  60. package/dist/analyzers/quality/gather.d.ts +38 -0
  61. package/dist/analyzers/quality/gather.d.ts.map +1 -0
  62. package/dist/analyzers/quality/gather.js +279 -0
  63. package/dist/analyzers/quality/gather.js.map +1 -0
  64. package/dist/analyzers/quality/index.d.ts +12 -0
  65. package/dist/analyzers/quality/index.d.ts.map +1 -0
  66. package/dist/analyzers/quality/index.js +281 -0
  67. package/dist/analyzers/quality/index.js.map +1 -0
  68. package/dist/analyzers/quality/shallow.d.ts +9 -0
  69. package/dist/analyzers/quality/shallow.d.ts.map +1 -0
  70. package/dist/analyzers/quality/shallow.js +8 -0
  71. package/dist/analyzers/quality/shallow.js.map +1 -0
  72. package/dist/analyzers/quality/types.d.ts +66 -0
  73. package/dist/analyzers/quality/types.d.ts.map +1 -0
  74. package/dist/analyzers/quality/types.js +3 -0
  75. package/dist/analyzers/quality/types.js.map +1 -0
  76. package/dist/analyzers/remediation.d.ts +42 -0
  77. package/dist/analyzers/remediation.d.ts.map +1 -0
  78. package/dist/analyzers/remediation.js +28 -0
  79. package/dist/analyzers/remediation.js.map +1 -0
  80. package/dist/analyzers/scoring.d.ts +32 -0
  81. package/dist/analyzers/scoring.d.ts.map +1 -0
  82. package/dist/analyzers/scoring.js +410 -0
  83. package/dist/analyzers/scoring.js.map +1 -0
  84. package/dist/analyzers/security/actions.d.ts +7 -0
  85. package/dist/analyzers/security/actions.d.ts.map +1 -0
  86. package/dist/analyzers/security/actions.js +104 -0
  87. package/dist/analyzers/security/actions.js.map +1 -0
  88. package/dist/analyzers/security/detailed.d.ts +14 -0
  89. package/dist/analyzers/security/detailed.d.ts.map +1 -0
  90. package/dist/analyzers/security/detailed.js +124 -0
  91. package/dist/analyzers/security/detailed.js.map +1 -0
  92. package/dist/analyzers/security/gather.d.ts +12 -0
  93. package/dist/analyzers/security/gather.d.ts.map +1 -0
  94. package/dist/analyzers/security/gather.js +195 -0
  95. package/dist/analyzers/security/gather.js.map +1 -0
  96. package/dist/analyzers/security/index.d.ts +8 -0
  97. package/dist/analyzers/security/index.d.ts.map +1 -0
  98. package/dist/analyzers/security/index.js +173 -0
  99. package/dist/analyzers/security/index.js.map +1 -0
  100. package/dist/analyzers/security/scoring.d.ts +29 -0
  101. package/dist/analyzers/security/scoring.d.ts.map +1 -0
  102. package/dist/analyzers/security/scoring.js +40 -0
  103. package/dist/analyzers/security/scoring.js.map +1 -0
  104. package/dist/analyzers/security/shallow.d.ts +10 -0
  105. package/dist/analyzers/security/shallow.d.ts.map +1 -0
  106. package/dist/analyzers/security/shallow.js +8 -0
  107. package/dist/analyzers/security/shallow.js.map +1 -0
  108. package/dist/analyzers/security/types.d.ts +43 -0
  109. package/dist/analyzers/security/types.d.ts.map +1 -0
  110. package/dist/analyzers/security/types.js +6 -0
  111. package/dist/analyzers/security/types.js.map +1 -0
  112. package/dist/analyzers/tests/actions.d.ts +6 -0
  113. package/dist/analyzers/tests/actions.d.ts.map +1 -0
  114. package/dist/analyzers/tests/actions.js +80 -0
  115. package/dist/analyzers/tests/actions.js.map +1 -0
  116. package/dist/analyzers/tests/detailed.d.ts +14 -0
  117. package/dist/analyzers/tests/detailed.d.ts.map +1 -0
  118. package/dist/analyzers/tests/detailed.js +121 -0
  119. package/dist/analyzers/tests/detailed.js.map +1 -0
  120. package/dist/analyzers/tests/gather.d.ts +5 -0
  121. package/dist/analyzers/tests/gather.d.ts.map +1 -0
  122. package/dist/analyzers/tests/gather.js +270 -0
  123. package/dist/analyzers/tests/gather.js.map +1 -0
  124. package/dist/analyzers/tests/import-graph.d.ts +48 -0
  125. package/dist/analyzers/tests/import-graph.d.ts.map +1 -0
  126. package/dist/analyzers/tests/import-graph.js +231 -0
  127. package/dist/analyzers/tests/import-graph.js.map +1 -0
  128. package/dist/analyzers/tests/index.d.ts +8 -0
  129. package/dist/analyzers/tests/index.d.ts.map +1 -0
  130. package/dist/analyzers/tests/index.js +247 -0
  131. package/dist/analyzers/tests/index.js.map +1 -0
  132. package/dist/analyzers/tests/scoring.d.ts +27 -0
  133. package/dist/analyzers/tests/scoring.d.ts.map +1 -0
  134. package/dist/analyzers/tests/scoring.js +38 -0
  135. package/dist/analyzers/tests/scoring.js.map +1 -0
  136. package/dist/analyzers/tests/shallow.d.ts +9 -0
  137. package/dist/analyzers/tests/shallow.d.ts.map +1 -0
  138. package/dist/analyzers/tests/shallow.js +8 -0
  139. package/dist/analyzers/tests/shallow.js.map +1 -0
  140. package/dist/analyzers/tests/types.d.ts +49 -0
  141. package/dist/analyzers/tests/types.d.ts.map +1 -0
  142. package/dist/analyzers/tests/types.js +6 -0
  143. package/dist/analyzers/tests/types.js.map +1 -0
  144. package/dist/analyzers/tools/cloc.d.ts +8 -0
  145. package/dist/analyzers/tools/cloc.d.ts.map +1 -0
  146. package/dist/analyzers/tools/cloc.js +49 -0
  147. package/dist/analyzers/tools/cloc.js.map +1 -0
  148. package/dist/analyzers/tools/coverage.d.ts +59 -0
  149. package/dist/analyzers/tools/coverage.d.ts.map +1 -0
  150. package/dist/analyzers/tools/coverage.js +280 -0
  151. package/dist/analyzers/tools/coverage.js.map +1 -0
  152. package/dist/analyzers/tools/cvss-v4-lookup.d.ts +10 -0
  153. package/dist/analyzers/tools/cvss-v4-lookup.d.ts.map +1 -0
  154. package/dist/analyzers/tools/cvss-v4-lookup.js +284 -0
  155. package/dist/analyzers/tools/cvss-v4-lookup.js.map +1 -0
  156. package/dist/analyzers/tools/cvss-v4.d.ts +24 -0
  157. package/dist/analyzers/tools/cvss-v4.d.ts.map +1 -0
  158. package/dist/analyzers/tools/cvss-v4.js +362 -0
  159. package/dist/analyzers/tools/cvss-v4.js.map +1 -0
  160. package/dist/analyzers/tools/default-exclusions.gitignore +56 -0
  161. package/dist/analyzers/tools/exclusions.d.ts +70 -0
  162. package/dist/analyzers/tools/exclusions.d.ts.map +1 -0
  163. package/dist/analyzers/tools/exclusions.js +250 -0
  164. package/dist/analyzers/tools/exclusions.js.map +1 -0
  165. package/dist/analyzers/tools/generic.d.ts +4 -0
  166. package/dist/analyzers/tools/generic.d.ts.map +1 -0
  167. package/dist/analyzers/tools/generic.js +198 -0
  168. package/dist/analyzers/tools/generic.js.map +1 -0
  169. package/dist/analyzers/tools/gitleaks.d.ts +8 -0
  170. package/dist/analyzers/tools/gitleaks.d.ts.map +1 -0
  171. package/dist/analyzers/tools/gitleaks.js +58 -0
  172. package/dist/analyzers/tools/gitleaks.js.map +1 -0
  173. package/dist/analyzers/tools/graphify.d.ts +4 -0
  174. package/dist/analyzers/tools/graphify.d.ts.map +1 -0
  175. package/dist/analyzers/tools/graphify.js +222 -0
  176. package/dist/analyzers/tools/graphify.js.map +1 -0
  177. package/dist/analyzers/tools/osv.d.ts +51 -0
  178. package/dist/analyzers/tools/osv.d.ts.map +1 -0
  179. package/dist/analyzers/tools/osv.js +188 -0
  180. package/dist/analyzers/tools/osv.js.map +1 -0
  181. package/dist/analyzers/tools/parallel.d.ts +8 -0
  182. package/dist/analyzers/tools/parallel.d.ts.map +1 -0
  183. package/dist/analyzers/tools/parallel.js +195 -0
  184. package/dist/analyzers/tools/parallel.js.map +1 -0
  185. package/dist/analyzers/tools/runner.d.ts +13 -0
  186. package/dist/analyzers/tools/runner.d.ts.map +1 -0
  187. package/dist/analyzers/tools/runner.js +109 -0
  188. package/dist/analyzers/tools/runner.js.map +1 -0
  189. package/dist/analyzers/tools/suppressions.d.ts +55 -0
  190. package/dist/analyzers/tools/suppressions.d.ts.map +1 -0
  191. package/dist/analyzers/tools/suppressions.js +203 -0
  192. package/dist/analyzers/tools/suppressions.js.map +1 -0
  193. package/dist/analyzers/tools/timing.d.ts +9 -0
  194. package/dist/analyzers/tools/timing.d.ts.map +1 -0
  195. package/dist/analyzers/tools/timing.js +29 -0
  196. package/dist/analyzers/tools/timing.js.map +1 -0
  197. package/dist/analyzers/tools/tool-registry.d.ts +86 -0
  198. package/dist/analyzers/tools/tool-registry.d.ts.map +1 -0
  199. package/dist/analyzers/tools/tool-registry.js +705 -0
  200. package/dist/analyzers/tools/tool-registry.js.map +1 -0
  201. package/dist/analyzers/types.d.ts +125 -0
  202. package/dist/analyzers/types.d.ts.map +1 -0
  203. package/dist/analyzers/types.js +11 -0
  204. package/dist/analyzers/types.js.map +1 -0
  205. package/dist/cli.d.ts.map +1 -1
  206. package/dist/cli.js +405 -0
  207. package/dist/cli.js.map +1 -1
  208. package/dist/detect.d.ts.map +1 -1
  209. package/dist/detect.js +24 -15
  210. package/dist/detect.js.map +1 -1
  211. package/dist/languages/csharp.d.ts +5 -0
  212. package/dist/languages/csharp.d.ts.map +1 -0
  213. package/dist/languages/csharp.js +265 -0
  214. package/dist/languages/csharp.js.map +1 -0
  215. package/dist/languages/go.d.ts +11 -0
  216. package/dist/languages/go.d.ts.map +1 -0
  217. package/dist/languages/go.js +321 -0
  218. package/dist/languages/go.js.map +1 -0
  219. package/dist/languages/index.d.ts +6 -0
  220. package/dist/languages/index.d.ts.map +1 -0
  221. package/dist/languages/index.js +18 -0
  222. package/dist/languages/index.js.map +1 -0
  223. package/dist/languages/python.d.ts +3 -0
  224. package/dist/languages/python.d.ts.map +1 -0
  225. package/dist/languages/python.js +284 -0
  226. package/dist/languages/python.js.map +1 -0
  227. package/dist/languages/rust.d.ts +17 -0
  228. package/dist/languages/rust.d.ts.map +1 -0
  229. package/dist/languages/rust.js +333 -0
  230. package/dist/languages/rust.js.map +1 -0
  231. package/dist/languages/types.d.ts +38 -0
  232. package/dist/languages/types.d.ts.map +1 -0
  233. package/dist/languages/types.js +3 -0
  234. package/dist/languages/types.js.map +1 -0
  235. package/dist/languages/typescript.d.ts +15 -0
  236. package/dist/languages/typescript.d.ts.map +1 -0
  237. package/dist/languages/typescript.js +353 -0
  238. package/dist/languages/typescript.js.map +1 -0
  239. package/dist/logger.d.ts +1 -0
  240. package/dist/logger.d.ts.map +1 -1
  241. package/dist/logger.js +25 -12
  242. package/dist/logger.js.map +1 -1
  243. package/dist/project-yaml.d.ts.map +1 -1
  244. package/dist/project-yaml.js +1 -0
  245. package/dist/project-yaml.js.map +1 -1
  246. package/dist/tools-cli.d.ts +2 -0
  247. package/dist/tools-cli.d.ts.map +1 -0
  248. package/dist/tools-cli.js +231 -0
  249. package/dist/tools-cli.js.map +1 -0
  250. package/dist/types.d.ts +10 -0
  251. package/dist/types.d.ts.map +1 -1
  252. package/package.json +6 -2
  253. package/templates/.claude/commands/dev-report.md +34 -4
  254. package/templates/.claude/commands/health.md +45 -2
  255. package/templates/.claude/commands/quality.md.template +38 -15
  256. package/templates/.claude/commands/test-gaps.md +36 -2
  257. package/templates/.claude/commands/vulnerabilities.md +36 -2
@@ -0,0 +1,195 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.gatherLayer2Parallel = gatherLayer2Parallel;
37
+ /**
38
+ * Parallel tool execution — run Layer 2 gather functions concurrently
39
+ * by forking child processes that call the EXISTING gather functions.
40
+ *
41
+ * Each child process requires the built dist/ module and calls the same
42
+ * gather function that sequential mode uses. NO duplicated invocation logic.
43
+ *
44
+ * Architecture rule (CLAUDE.md #2): each tool has ONE gather function.
45
+ * This module orchestrates, never reimplements.
46
+ */
47
+ const fs = __importStar(require("fs"));
48
+ const path = __importStar(require("path"));
49
+ const os = __importStar(require("os"));
50
+ const child_process_1 = require("child_process");
51
+ /**
52
+ * Run cloc + gitleaks + graphify gather functions in parallel child processes.
53
+ * Each child calls the real gather function from the existing tool module.
54
+ * Falls back to sequential on low memory (<1GB free).
55
+ */
56
+ function gatherLayer2Parallel(cwd, verbose = false) {
57
+ const dxkitDist = path.resolve(__dirname, '..');
58
+ const tasks = [
59
+ {
60
+ name: 'cloc',
61
+ modulePath: './cloc',
62
+ functionName: 'gatherClocMetrics',
63
+ },
64
+ {
65
+ name: 'gitleaks',
66
+ modulePath: './gitleaks',
67
+ functionName: 'gatherGitleaksMetrics',
68
+ },
69
+ {
70
+ name: 'graphify',
71
+ modulePath: './graphify',
72
+ functionName: 'gatherGraphifyMetrics',
73
+ },
74
+ ];
75
+ // Check available memory — fall back to sequential if <1GB free
76
+ const freeMem = os.freemem();
77
+ const useParallel = freeMem >= 1024 * 1024 * 1024;
78
+ if (verbose && !useParallel) {
79
+ console.error(` [parallel] Low memory (${Math.round(freeMem / 1024 / 1024)}MB free), running sequentially`);
80
+ }
81
+ const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'dxkit-l2-'));
82
+ const startTime = Date.now();
83
+ if (useParallel) {
84
+ runTasksParallel(tasks, cwd, dxkitDist, tmpDir, verbose);
85
+ }
86
+ else {
87
+ runTasksSequential(tasks, cwd, dxkitDist, tmpDir);
88
+ }
89
+ if (verbose) {
90
+ const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);
91
+ console.error(` [parallel] Layer 2 completed in ${elapsed}s`);
92
+ }
93
+ // Merge all results
94
+ const merged = {
95
+ toolsUsed: [],
96
+ toolsUnavailable: [],
97
+ };
98
+ for (let i = 0; i < tasks.length; i++) {
99
+ const resultFile = path.join(tmpDir, `${tasks[i].name}.json`);
100
+ try {
101
+ const raw = fs.readFileSync(resultFile, 'utf-8');
102
+ const partial = JSON.parse(raw);
103
+ // Merge arrays
104
+ if (partial.toolsUsed) {
105
+ merged.toolsUsed.push(...partial.toolsUsed);
106
+ delete partial.toolsUsed;
107
+ }
108
+ if (partial.toolsUnavailable) {
109
+ merged.toolsUnavailable.push(...partial.toolsUnavailable);
110
+ delete partial.toolsUnavailable;
111
+ }
112
+ // Merge non-null values
113
+ for (const [k, v] of Object.entries(partial)) {
114
+ if (v !== null && v !== undefined) {
115
+ merged[k] = v;
116
+ }
117
+ }
118
+ }
119
+ catch {
120
+ // Tool didn't produce output — skip
121
+ }
122
+ }
123
+ // Cleanup
124
+ try {
125
+ fs.rmSync(tmpDir, { recursive: true, force: true });
126
+ }
127
+ catch {
128
+ /* ignore */
129
+ }
130
+ return merged;
131
+ }
132
+ /** Build the Node.js script that calls a gather function and writes result to file. */
133
+ function buildWorkerScript(task, cwd, resultFile) {
134
+ // The child process requires the SAME compiled module and calls the SAME function.
135
+ // No duplication — it's literally require('<abs-path>/tools/cloc').gatherClocMetrics(cwd).
136
+ // Use __dirname at build time to resolve the absolute path to dist/analyzers/.
137
+ const absModulePath = path.resolve(__dirname, task.modulePath);
138
+ return `
139
+ try {
140
+ var mod = require('${absModulePath.replace(/\\/g, '/')}');
141
+ var result = mod.${task.functionName}('${cwd.replace(/'/g, "\\'")}');
142
+ require('fs').writeFileSync('${resultFile}', JSON.stringify(result));
143
+ } catch (e) {
144
+ require('fs').writeFileSync('${resultFile}', JSON.stringify({
145
+ toolsUnavailable: ['${task.name} (child process error: ' + (e.message || '').slice(0, 100) + ')']
146
+ }));
147
+ }
148
+ `;
149
+ }
150
+ function runTasksParallel(tasks, cwd, dxkitDist, tmpDir, _verbose) {
151
+ // Write each task as a standalone Node script file, then run all via bash `&` + `wait`.
152
+ // This gives true OS-level parallelism without poll overhead.
153
+ const scriptPaths = [];
154
+ for (const task of tasks) {
155
+ const resultFile = path.join(tmpDir, `${task.name}.json`);
156
+ const workerScript = buildWorkerScript(task, cwd, resultFile);
157
+ const scriptPath = path.join(tmpDir, `${task.name}.js`);
158
+ fs.writeFileSync(scriptPath, workerScript);
159
+ scriptPaths.push(scriptPath);
160
+ }
161
+ // Bash script that backgrounds all node processes and waits
162
+ const bashLines = scriptPaths.map((sp) => `node '${sp}' &`);
163
+ bashLines.push('wait');
164
+ const bashScript = path.join(tmpDir, 'run-parallel.sh');
165
+ fs.writeFileSync(bashScript, '#!/bin/bash\n' + bashLines.join('\n') + '\n');
166
+ fs.chmodSync(bashScript, 0o755);
167
+ try {
168
+ (0, child_process_1.execSync)(bashScript, {
169
+ cwd: dxkitDist,
170
+ stdio: 'ignore',
171
+ timeout: 300000,
172
+ env: process.env,
173
+ });
174
+ }
175
+ catch {
176
+ // Timeout or error — still try to read whatever completed
177
+ }
178
+ }
179
+ function runTasksSequential(tasks, cwd, dxkitDist, tmpDir) {
180
+ for (const task of tasks) {
181
+ const resultFile = path.join(tmpDir, `${task.name}.json`);
182
+ const script = buildWorkerScript(task, cwd, resultFile);
183
+ try {
184
+ (0, child_process_1.execSync)(`node -e '${script.replace(/'/g, "'\\''")}'`, {
185
+ cwd: dxkitDist,
186
+ stdio: 'ignore',
187
+ timeout: 180000,
188
+ });
189
+ }
190
+ catch {
191
+ /* continue with next tool */
192
+ }
193
+ }
194
+ }
195
+ //# sourceMappingURL=parallel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parallel.js","sourceRoot":"","sources":["../../../src/analyzers/tools/parallel.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /** Run a command and return stdout. Returns empty string on failure. */
2
+ export declare function run(cmd: string, cwd: string, timeoutMs?: number): string;
3
+ /** Run a command and return the exit code. */
4
+ export declare function runExitCode(cmd: string, cwd: string, timeoutMs?: number): number;
5
+ /** Run a command and parse stdout as JSON. Returns null on failure. */
6
+ export declare function runJSON<T>(cmd: string, cwd: string, timeoutMs?: number): T | null;
7
+ /** Count lines in command output. */
8
+ export declare function countLines(cmd: string, cwd: string): number;
9
+ /** Check if a command is available. */
10
+ export declare function commandExists(cmd: string, cwd: string): boolean;
11
+ /** Check if a file exists relative to cwd. */
12
+ export declare function fileExists(cwd: string, ...paths: string[]): boolean;
13
+ //# sourceMappingURL=runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../../src/analyzers/tools/runner.ts"],"names":[],"mappings":"AAOA,wEAAwE;AACxE,wBAAgB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,SAAQ,GAAG,MAAM,CAgBvE;AAED,8CAA8C;AAC9C,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,SAAQ,GAAG,MAAM,CAY/E;AAED,uEAAuE;AACvE,wBAAgB,OAAO,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,SAAQ,GAAG,CAAC,GAAG,IAAI,CAQhF;AAED,qCAAqC;AACrC,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAI3D;AAED,uCAAuC;AACvC,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAE/D;AAED,8CAA8C;AAC9C,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAEnE"}
@@ -0,0 +1,109 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.run = run;
37
+ exports.runExitCode = runExitCode;
38
+ exports.runJSON = runJSON;
39
+ exports.countLines = countLines;
40
+ exports.commandExists = commandExists;
41
+ exports.fileExists = fileExists;
42
+ /**
43
+ * Tool runner utilities -- safe command execution and output parsing.
44
+ */
45
+ const child_process_1 = require("child_process");
46
+ const fs = __importStar(require("fs"));
47
+ const path = __importStar(require("path"));
48
+ /** Run a command and return stdout. Returns empty string on failure. */
49
+ function run(cmd, cwd, timeoutMs = 30000) {
50
+ try {
51
+ return (0, child_process_1.execSync)(cmd, {
52
+ cwd,
53
+ encoding: 'utf-8',
54
+ stdio: ['pipe', 'pipe', 'pipe'],
55
+ timeout: timeoutMs,
56
+ }).trim();
57
+ }
58
+ catch (err) {
59
+ // Some tools (npm audit) write valid output to stdout even on non-zero exit
60
+ const e = err;
61
+ if (e.stdout && typeof e.stdout === 'string') {
62
+ return e.stdout.trim();
63
+ }
64
+ return '';
65
+ }
66
+ }
67
+ /** Run a command and return the exit code. */
68
+ function runExitCode(cmd, cwd, timeoutMs = 60000) {
69
+ try {
70
+ (0, child_process_1.execSync)(cmd, {
71
+ cwd,
72
+ stdio: ['pipe', 'pipe', 'pipe'],
73
+ timeout: timeoutMs,
74
+ });
75
+ return 0;
76
+ }
77
+ catch (err) {
78
+ const e = err;
79
+ return e.status ?? 1;
80
+ }
81
+ }
82
+ /** Run a command and parse stdout as JSON. Returns null on failure. */
83
+ function runJSON(cmd, cwd, timeoutMs = 60000) {
84
+ const output = run(cmd, cwd, timeoutMs);
85
+ if (!output)
86
+ return null;
87
+ try {
88
+ return JSON.parse(output);
89
+ }
90
+ catch {
91
+ return null;
92
+ }
93
+ }
94
+ /** Count lines in command output. */
95
+ function countLines(cmd, cwd) {
96
+ const output = run(cmd, cwd);
97
+ if (!output)
98
+ return 0;
99
+ return output.split('\n').filter((l) => l.trim()).length;
100
+ }
101
+ /** Check if a command is available. */
102
+ function commandExists(cmd, cwd) {
103
+ return run(`which ${cmd} 2>/dev/null`, cwd) !== '';
104
+ }
105
+ /** Check if a file exists relative to cwd. */
106
+ function fileExists(cwd, ...paths) {
107
+ return paths.some((p) => fs.existsSync(path.join(cwd, p)));
108
+ }
109
+ //# sourceMappingURL=runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../../../src/analyzers/tools/runner.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAQA,kBAgBC;AAGD,kCAYC;AAGD,0BAQC;AAGD,gCAIC;AAGD,sCAEC;AAGD,gCAEC;AAnED;;GAEG;AACH,iDAAyC;AACzC,uCAAyB;AACzB,2CAA6B;AAE7B,wEAAwE;AACxE,SAAgB,GAAG,CAAC,GAAW,EAAE,GAAW,EAAE,SAAS,GAAG,KAAK;IAC7D,IAAI,CAAC;QACH,OAAO,IAAA,wBAAQ,EAAC,GAAG,EAAE;YACnB,GAAG;YACH,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;YAC/B,OAAO,EAAE,SAAS;SACnB,CAAC,CAAC,IAAI,EAAE,CAAC;IACZ,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,4EAA4E;QAC5E,MAAM,CAAC,GAAG,GAA0B,CAAC;QACrC,IAAI,CAAC,CAAC,MAAM,IAAI,OAAO,CAAC,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YAC7C,OAAO,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QACzB,CAAC;QACD,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,8CAA8C;AAC9C,SAAgB,WAAW,CAAC,GAAW,EAAE,GAAW,EAAE,SAAS,GAAG,KAAK;IACrE,IAAI,CAAC;QACH,IAAA,wBAAQ,EAAC,GAAG,EAAE;YACZ,GAAG;YACH,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;YAC/B,OAAO,EAAE,SAAS;SACnB,CAAC,CAAC;QACH,OAAO,CAAC,CAAC;IACX,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,MAAM,CAAC,GAAG,GAA0B,CAAC;QACrC,OAAO,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC;IACvB,CAAC;AACH,CAAC;AAED,uEAAuE;AACvE,SAAgB,OAAO,CAAI,GAAW,EAAE,GAAW,EAAE,SAAS,GAAG,KAAK;IACpE,MAAM,MAAM,GAAG,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC;IACxC,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACzB,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAM,CAAC;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,qCAAqC;AACrC,SAAgB,UAAU,CAAC,GAAW,EAAE,GAAW;IACjD,MAAM,MAAM,GAAG,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAC7B,IAAI,CAAC,MAAM;QAAE,OAAO,CAAC,CAAC;IACtB,OAAO,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;AAC3D,CAAC;AAED,uCAAuC;AACvC,SAAgB,aAAa,CAAC,GAAW,EAAE,GAAW;IACpD,OAAO,GAAG,CAAC,SAAS,GAAG,cAAc,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC;AACrD,CAAC;AAED,8CAA8C;AAC9C,SAAgB,UAAU,CAAC,GAAW,EAAE,GAAG,KAAe;IACxD,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7D,CAAC"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * User-defined suppressions for scanner findings.
3
+ *
4
+ * Reads `.dxkit-suppressions.json` at the repo root. Example:
5
+ *
6
+ * {
7
+ * "gitleaks": [
8
+ * { "rule": "generic-api-key", "paths": ["test/fixtures/**"], "reason": "fake keys in fixtures" }
9
+ * ],
10
+ * "semgrep": [
11
+ * { "rule": "*", "paths": ["scripts/migrations/**"], "reason": "legacy, grandfathered" }
12
+ * ]
13
+ * }
14
+ *
15
+ * A finding is suppressed when:
16
+ * - its rule matches an entry's `rule` (exact string, or "*" as wildcard), AND
17
+ * - its path matches at least one of the entry's `paths` globs.
18
+ *
19
+ * Globs support `**` (any path segments), `*` (any chars except `/`), and `?`.
20
+ * Leading `./` is normalized away.
21
+ */
22
+ export interface SuppressionRule {
23
+ /** Rule ID to match, or "*" for any rule from this tool. */
24
+ rule: string;
25
+ /** Glob patterns (relative to repo root) — finding suppressed if any match. */
26
+ paths: string[];
27
+ /** Optional human-readable reason (surfaced in reports). */
28
+ reason?: string;
29
+ }
30
+ export interface Suppressions {
31
+ gitleaks: SuppressionRule[];
32
+ semgrep: SuppressionRule[];
33
+ slop: SuppressionRule[];
34
+ }
35
+ /** Load suppressions for a repo root, memoized. Returns empty suppressions if file is missing/malformed. */
36
+ export declare function loadSuppressions(cwd: string): Suppressions;
37
+ /** Clear memo — useful for tests. */
38
+ export declare function clearSuppressionsCache(): void;
39
+ /**
40
+ * Apply suppressions to a set of findings.
41
+ *
42
+ * Callers pass accessors (findings vary in shape across tools). Returns the
43
+ * kept findings plus a parallel list of suppressed findings with the matched
44
+ * reason annotated.
45
+ */
46
+ export declare function applySuppressions<T>(findings: T[], rules: SuppressionRule[], getRule: (f: T) => string, getPath: (f: T) => string): {
47
+ kept: T[];
48
+ suppressed: Array<{
49
+ finding: T;
50
+ reason?: string;
51
+ }>;
52
+ };
53
+ /** Convert a glob pattern to an anchored regex. Supports `**`, `*`, `?`. */
54
+ export declare function globToRegex(glob: string): RegExp;
55
+ //# sourceMappingURL=suppressions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"suppressions.d.ts","sourceRoot":"","sources":["../../../src/analyzers/tools/suppressions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAKH,MAAM,WAAW,eAAe;IAC9B,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAC;IACb,+EAA+E;IAC/E,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,4DAA4D;IAC5D,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,IAAI,EAAE,eAAe,EAAE,CAAC;CACzB;AAMD,4GAA4G;AAC5G,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,CA4B1D;AAED,qCAAqC;AACrC,wBAAgB,sBAAsB,IAAI,IAAI,CAE7C;AAkBD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EACjC,QAAQ,EAAE,CAAC,EAAE,EACb,KAAK,EAAE,eAAe,EAAE,EACxB,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,EACzB,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,GACxB;IAAE,IAAI,EAAE,CAAC,EAAE,CAAC;IAAC,UAAU,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,CAiCnE;AAED,4EAA4E;AAC5E,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAuChD"}
@@ -0,0 +1,203 @@
1
+ "use strict";
2
+ /**
3
+ * User-defined suppressions for scanner findings.
4
+ *
5
+ * Reads `.dxkit-suppressions.json` at the repo root. Example:
6
+ *
7
+ * {
8
+ * "gitleaks": [
9
+ * { "rule": "generic-api-key", "paths": ["test/fixtures/**"], "reason": "fake keys in fixtures" }
10
+ * ],
11
+ * "semgrep": [
12
+ * { "rule": "*", "paths": ["scripts/migrations/**"], "reason": "legacy, grandfathered" }
13
+ * ]
14
+ * }
15
+ *
16
+ * A finding is suppressed when:
17
+ * - its rule matches an entry's `rule` (exact string, or "*" as wildcard), AND
18
+ * - its path matches at least one of the entry's `paths` globs.
19
+ *
20
+ * Globs support `**` (any path segments), `*` (any chars except `/`), and `?`.
21
+ * Leading `./` is normalized away.
22
+ */
23
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
24
+ if (k2 === undefined) k2 = k;
25
+ var desc = Object.getOwnPropertyDescriptor(m, k);
26
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
27
+ desc = { enumerable: true, get: function() { return m[k]; } };
28
+ }
29
+ Object.defineProperty(o, k2, desc);
30
+ }) : (function(o, m, k, k2) {
31
+ if (k2 === undefined) k2 = k;
32
+ o[k2] = m[k];
33
+ }));
34
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
35
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
36
+ }) : function(o, v) {
37
+ o["default"] = v;
38
+ });
39
+ var __importStar = (this && this.__importStar) || (function () {
40
+ var ownKeys = function(o) {
41
+ ownKeys = Object.getOwnPropertyNames || function (o) {
42
+ var ar = [];
43
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
44
+ return ar;
45
+ };
46
+ return ownKeys(o);
47
+ };
48
+ return function (mod) {
49
+ if (mod && mod.__esModule) return mod;
50
+ var result = {};
51
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
52
+ __setModuleDefault(result, mod);
53
+ return result;
54
+ };
55
+ })();
56
+ Object.defineProperty(exports, "__esModule", { value: true });
57
+ exports.loadSuppressions = loadSuppressions;
58
+ exports.clearSuppressionsCache = clearSuppressionsCache;
59
+ exports.applySuppressions = applySuppressions;
60
+ exports.globToRegex = globToRegex;
61
+ const fs = __importStar(require("fs"));
62
+ const path = __importStar(require("path"));
63
+ const EMPTY = { gitleaks: [], semgrep: [], slop: [] };
64
+ const cache = new Map();
65
+ /** Load suppressions for a repo root, memoized. Returns empty suppressions if file is missing/malformed. */
66
+ function loadSuppressions(cwd) {
67
+ const hit = cache.get(cwd);
68
+ if (hit)
69
+ return hit;
70
+ const filePath = path.join(cwd, '.dxkit-suppressions.json');
71
+ let raw;
72
+ try {
73
+ raw = fs.readFileSync(filePath, 'utf-8');
74
+ }
75
+ catch {
76
+ cache.set(cwd, EMPTY);
77
+ return EMPTY;
78
+ }
79
+ let parsed;
80
+ try {
81
+ parsed = JSON.parse(raw);
82
+ }
83
+ catch {
84
+ cache.set(cwd, EMPTY);
85
+ return EMPTY;
86
+ }
87
+ const resolved = {
88
+ gitleaks: extractRules(parsed, 'gitleaks'),
89
+ semgrep: extractRules(parsed, 'semgrep'),
90
+ slop: extractRules(parsed, 'slop'),
91
+ };
92
+ cache.set(cwd, resolved);
93
+ return resolved;
94
+ }
95
+ /** Clear memo — useful for tests. */
96
+ function clearSuppressionsCache() {
97
+ cache.clear();
98
+ }
99
+ function extractRules(parsed, key) {
100
+ if (!parsed || typeof parsed !== 'object')
101
+ return [];
102
+ const bucket = parsed[key];
103
+ if (!Array.isArray(bucket))
104
+ return [];
105
+ return bucket
106
+ .filter((e) => !!e && typeof e === 'object')
107
+ .map((e) => ({
108
+ rule: typeof e.rule === 'string' ? e.rule : '',
109
+ paths: Array.isArray(e.paths)
110
+ ? e.paths.filter((p) => typeof p === 'string')
111
+ : [],
112
+ reason: typeof e.reason === 'string' ? e.reason : undefined,
113
+ }))
114
+ .filter((r) => r.rule && r.paths.length > 0);
115
+ }
116
+ /**
117
+ * Apply suppressions to a set of findings.
118
+ *
119
+ * Callers pass accessors (findings vary in shape across tools). Returns the
120
+ * kept findings plus a parallel list of suppressed findings with the matched
121
+ * reason annotated.
122
+ */
123
+ function applySuppressions(findings, rules, getRule, getPath) {
124
+ if (rules.length === 0)
125
+ return { kept: findings, suppressed: [] };
126
+ const compiled = rules.map((r) => ({
127
+ rule: r.rule,
128
+ regexes: r.paths.map(globToRegex),
129
+ reason: r.reason,
130
+ }));
131
+ const kept = [];
132
+ const suppressed = [];
133
+ for (const f of findings) {
134
+ const fRule = getRule(f);
135
+ const fPath = normalizePath(getPath(f));
136
+ let matched = null;
137
+ for (const c of compiled) {
138
+ if (c.rule !== '*' && c.rule !== fRule)
139
+ continue;
140
+ if (c.regexes.some((re) => re.test(fPath))) {
141
+ matched = { reason: c.reason };
142
+ break;
143
+ }
144
+ }
145
+ if (matched) {
146
+ suppressed.push({ finding: f, reason: matched.reason });
147
+ }
148
+ else {
149
+ kept.push(f);
150
+ }
151
+ }
152
+ return { kept, suppressed };
153
+ }
154
+ /** Convert a glob pattern to an anchored regex. Supports `**`, `*`, `?`. */
155
+ function globToRegex(glob) {
156
+ let g = glob;
157
+ if (g.startsWith('./'))
158
+ g = g.slice(2);
159
+ let re = '';
160
+ let i = 0;
161
+ while (i < g.length) {
162
+ // leading or mid-path `**/` — optional path prefix
163
+ if (g.startsWith('**/', i)) {
164
+ re += '(?:.*/)?';
165
+ i += 3;
166
+ continue;
167
+ }
168
+ // trailing `/**` — optional path suffix
169
+ if (i + 3 === g.length && g.startsWith('/**', i)) {
170
+ re += '(?:/.*)?';
171
+ i += 3;
172
+ continue;
173
+ }
174
+ // bare `**` — any chars including slashes
175
+ if (g.startsWith('**', i)) {
176
+ re += '.*';
177
+ i += 2;
178
+ continue;
179
+ }
180
+ const c = g[i];
181
+ if (c === '*') {
182
+ re += '[^/]*';
183
+ }
184
+ else if (c === '?') {
185
+ re += '[^/]';
186
+ }
187
+ else if ('.+()|[]{}^$\\'.includes(c)) {
188
+ re += '\\' + c;
189
+ }
190
+ else {
191
+ re += c;
192
+ }
193
+ i++;
194
+ }
195
+ return new RegExp('^' + re + '$');
196
+ }
197
+ function normalizePath(p) {
198
+ let n = p.replace(/\\/g, '/');
199
+ if (n.startsWith('./'))
200
+ n = n.slice(2);
201
+ return n;
202
+ }
203
+ //# sourceMappingURL=suppressions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"suppressions.js","sourceRoot":"","sources":["../../../src/analyzers/tools/suppressions.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyBH,4CA4BC;AAGD,wDAEC;AAyBD,8CAsCC;AAGD,kCAuCC;AAjKD,uCAAyB;AACzB,2CAA6B;AAiB7B,MAAM,KAAK,GAAiB,EAAE,QAAQ,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;AAEpE,MAAM,KAAK,GAAG,IAAI,GAAG,EAAwB,CAAC;AAE9C,4GAA4G;AAC5G,SAAgB,gBAAgB,CAAC,GAAW;IAC1C,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC3B,IAAI,GAAG;QAAE,OAAO,GAAG,CAAC;IAEpB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,0BAA0B,CAAC,CAAC;IAC5D,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC3C,CAAC;IAAC,MAAM,CAAC;QACP,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACtB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACtB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,QAAQ,GAAiB;QAC7B,QAAQ,EAAE,YAAY,CAAC,MAAM,EAAE,UAAU,CAAC;QAC1C,OAAO,EAAE,YAAY,CAAC,MAAM,EAAE,SAAS,CAAC;QACxC,IAAI,EAAE,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC;KACnC,CAAC;IACF,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IACzB,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,qCAAqC;AACrC,SAAgB,sBAAsB;IACpC,KAAK,CAAC,KAAK,EAAE,CAAC;AAChB,CAAC;AAED,SAAS,YAAY,CAAC,MAAe,EAAE,GAAW;IAChD,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ;QAAE,OAAO,EAAE,CAAC;IACrD,MAAM,MAAM,GAAI,MAAkC,CAAC,GAAG,CAAC,CAAC;IACxD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;QAAE,OAAO,EAAE,CAAC;IACtC,OAAO,MAAM;SACV,MAAM,CAAC,CAAC,CAAC,EAAgC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,CAAC;SACzE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACX,IAAI,EAAE,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;QAC9C,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;YAC3B,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC;YAC3D,CAAC,CAAC,EAAE;QACN,MAAM,EAAE,OAAO,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;KAC5D,CAAC,CAAC;SACF,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACjD,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,iBAAiB,CAC/B,QAAa,EACb,KAAwB,EACxB,OAAyB,EACzB,OAAyB;IAEzB,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC;IAElE,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACjC,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC;QACjC,MAAM,EAAE,CAAC,CAAC,MAAM;KACjB,CAAC,CAAC,CAAC;IAEJ,MAAM,IAAI,GAAQ,EAAE,CAAC;IACrB,MAAM,UAAU,GAA2C,EAAE,CAAC;IAE9D,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QACzB,MAAM,KAAK,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QACxC,IAAI,OAAO,GAA+B,IAAI,CAAC;QAE/C,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;YACzB,IAAI,CAAC,CAAC,IAAI,KAAK,GAAG,IAAI,CAAC,CAAC,IAAI,KAAK,KAAK;gBAAE,SAAS;YACjD,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;gBAC3C,OAAO,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;gBAC/B,MAAM;YACR,CAAC;QACH,CAAC;QAED,IAAI,OAAO,EAAE,CAAC;YACZ,UAAU,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QAC1D,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACf,CAAC;IACH,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;AAC9B,CAAC;AAED,4EAA4E;AAC5E,SAAgB,WAAW,CAAC,IAAY;IACtC,IAAI,CAAC,GAAG,IAAI,CAAC;IACb,IAAI,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAEvC,IAAI,EAAE,GAAG,EAAE,CAAC;IACZ,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC;QACpB,mDAAmD;QACnD,IAAI,CAAC,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC;YAC3B,EAAE,IAAI,UAAU,CAAC;YACjB,CAAC,IAAI,CAAC,CAAC;YACP,SAAS;QACX,CAAC;QACD,wCAAwC;QACxC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC;YACjD,EAAE,IAAI,UAAU,CAAC;YACjB,CAAC,IAAI,CAAC,CAAC;YACP,SAAS;QACX,CAAC;QACD,0CAA0C;QAC1C,IAAI,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;YAC1B,EAAE,IAAI,IAAI,CAAC;YACX,CAAC,IAAI,CAAC,CAAC;YACP,SAAS;QACX,CAAC;QAED,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACf,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;YACd,EAAE,IAAI,OAAO,CAAC;QAChB,CAAC;aAAM,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;YACrB,EAAE,IAAI,MAAM,CAAC;QACf,CAAC;aAAM,IAAI,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;YACvC,EAAE,IAAI,IAAI,GAAG,CAAC,CAAC;QACjB,CAAC;aAAM,CAAC;YACN,EAAE,IAAI,CAAC,CAAC;QACV,CAAC;QACD,CAAC,EAAE,CAAC;IACN,CAAC;IACD,OAAO,IAAI,MAAM,CAAC,GAAG,GAAG,EAAE,GAAG,GAAG,CAAC,CAAC;AACpC,CAAC;AAED,SAAS,aAAa,CAAC,CAAS;IAC9B,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC9B,IAAI,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACvC,OAAO,CAAC,CAAC;AACX,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Timing helper for --verbose output.
3
+ *
4
+ * Wrap a gather call to print per-tool elapsed time to stderr when verbose.
5
+ * Stdout stays clean so --json output is unaffected.
6
+ */
7
+ export declare function timed<T>(name: string, verbose: boolean, fn: () => T): T;
8
+ export declare function timedAsync<T>(name: string, verbose: boolean, fn: () => Promise<T>): Promise<T>;
9
+ //# sourceMappingURL=timing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timing.d.ts","sourceRoot":"","sources":["../../../src/analyzers/tools/timing.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,wBAAgB,KAAK,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAOvE;AAED,wBAAsB,UAAU,CAAC,CAAC,EAChC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,OAAO,EAChB,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACnB,OAAO,CAAC,CAAC,CAAC,CAOZ"}
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.timed = timed;
4
+ exports.timedAsync = timedAsync;
5
+ /**
6
+ * Timing helper for --verbose output.
7
+ *
8
+ * Wrap a gather call to print per-tool elapsed time to stderr when verbose.
9
+ * Stdout stays clean so --json output is unaffected.
10
+ */
11
+ function timed(name, verbose, fn) {
12
+ if (!verbose)
13
+ return fn();
14
+ const start = Date.now();
15
+ const result = fn();
16
+ const elapsed = ((Date.now() - start) / 1000).toFixed(2);
17
+ process.stderr.write(` [timing] ${name.padEnd(18)} ${elapsed}s\n`);
18
+ return result;
19
+ }
20
+ async function timedAsync(name, verbose, fn) {
21
+ if (!verbose)
22
+ return fn();
23
+ const start = Date.now();
24
+ const result = await fn();
25
+ const elapsed = ((Date.now() - start) / 1000).toFixed(2);
26
+ process.stderr.write(` [timing] ${name.padEnd(18)} ${elapsed}s\n`);
27
+ return result;
28
+ }
29
+ //# sourceMappingURL=timing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timing.js","sourceRoot":"","sources":["../../../src/analyzers/tools/timing.ts"],"names":[],"mappings":";;AAMA,sBAOC;AAED,gCAWC;AA1BD;;;;;GAKG;AACH,SAAgB,KAAK,CAAI,IAAY,EAAE,OAAgB,EAAE,EAAW;IAClE,IAAI,CAAC,OAAO;QAAE,OAAO,EAAE,EAAE,CAAC;IAC1B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACzB,MAAM,MAAM,GAAG,EAAE,EAAE,CAAC;IACpB,MAAM,OAAO,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IACzD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,cAAc,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,OAAO,KAAK,CAAC,CAAC;IACpE,OAAO,MAAM,CAAC;AAChB,CAAC;AAEM,KAAK,UAAU,UAAU,CAC9B,IAAY,EACZ,OAAgB,EAChB,EAAoB;IAEpB,IAAI,CAAC,OAAO;QAAE,OAAO,EAAE,EAAE,CAAC;IAC1B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACzB,MAAM,MAAM,GAAG,MAAM,EAAE,EAAE,CAAC;IAC1B,MAAM,OAAO,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IACzD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,cAAc,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,OAAO,KAAK,CAAC,CAAC;IACpE,OAAO,MAAM,CAAC;AAChB,CAAC"}