@vyuhlabs/dxkit 1.6.1 → 2.0.1

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 (210) hide show
  1. package/CHANGELOG.md +115 -0
  2. package/README.md +3 -3
  3. package/dist/agents/extract.d.ts +25 -0
  4. package/dist/agents/extract.d.ts.map +1 -0
  5. package/dist/agents/extract.js +186 -0
  6. package/dist/agents/extract.js.map +1 -0
  7. package/dist/agents/schemas.d.ts +106 -0
  8. package/dist/agents/schemas.d.ts.map +1 -0
  9. package/dist/agents/schemas.js +86 -0
  10. package/dist/agents/schemas.js.map +1 -0
  11. package/dist/agents/session.d.ts +28 -0
  12. package/dist/agents/session.d.ts.map +1 -0
  13. package/dist/agents/session.js +223 -0
  14. package/dist/agents/session.js.map +1 -0
  15. package/dist/analyzers/developer/detailed.js +1 -1
  16. package/dist/analyzers/developer/detailed.js.map +1 -1
  17. package/dist/analyzers/dispatcher.d.ts +36 -0
  18. package/dist/analyzers/dispatcher.d.ts.map +1 -0
  19. package/dist/analyzers/dispatcher.js +62 -0
  20. package/dist/analyzers/dispatcher.js.map +1 -0
  21. package/dist/analyzers/docs/shallow.d.ts +3 -2
  22. package/dist/analyzers/docs/shallow.d.ts.map +1 -1
  23. package/dist/analyzers/docs/shallow.js +2 -2
  24. package/dist/analyzers/docs/shallow.js.map +1 -1
  25. package/dist/analyzers/dx/shallow.d.ts +3 -2
  26. package/dist/analyzers/dx/shallow.d.ts.map +1 -1
  27. package/dist/analyzers/dx/shallow.js +2 -2
  28. package/dist/analyzers/dx/shallow.js.map +1 -1
  29. package/dist/analyzers/health/actions.d.ts +3 -3
  30. package/dist/analyzers/health/actions.d.ts.map +1 -1
  31. package/dist/analyzers/health/actions.js +99 -52
  32. package/dist/analyzers/health/actions.js.map +1 -1
  33. package/dist/analyzers/health/detailed.d.ts.map +1 -1
  34. package/dist/analyzers/health/detailed.js +6 -2
  35. package/dist/analyzers/health/detailed.js.map +1 -1
  36. package/dist/analyzers/health.d.ts +0 -2
  37. package/dist/analyzers/health.d.ts.map +1 -1
  38. package/dist/analyzers/health.js +134 -72
  39. package/dist/analyzers/health.js.map +1 -1
  40. package/dist/analyzers/maintainability/shallow.d.ts +3 -2
  41. package/dist/analyzers/maintainability/shallow.d.ts.map +1 -1
  42. package/dist/analyzers/maintainability/shallow.js +2 -2
  43. package/dist/analyzers/maintainability/shallow.js.map +1 -1
  44. package/dist/analyzers/quality/detailed.js +1 -1
  45. package/dist/analyzers/quality/detailed.js.map +1 -1
  46. package/dist/analyzers/quality/gather.d.ts +33 -4
  47. package/dist/analyzers/quality/gather.d.ts.map +1 -1
  48. package/dist/analyzers/quality/gather.js +81 -93
  49. package/dist/analyzers/quality/gather.js.map +1 -1
  50. package/dist/analyzers/quality/index.js +4 -4
  51. package/dist/analyzers/quality/index.js.map +1 -1
  52. package/dist/analyzers/quality/shallow.d.ts +3 -2
  53. package/dist/analyzers/quality/shallow.d.ts.map +1 -1
  54. package/dist/analyzers/quality/shallow.js +2 -2
  55. package/dist/analyzers/quality/shallow.js.map +1 -1
  56. package/dist/analyzers/scoring.d.ts +26 -9
  57. package/dist/analyzers/scoring.d.ts.map +1 -1
  58. package/dist/analyzers/scoring.js +83 -71
  59. package/dist/analyzers/scoring.js.map +1 -1
  60. package/dist/analyzers/security/detailed.js +1 -1
  61. package/dist/analyzers/security/detailed.js.map +1 -1
  62. package/dist/analyzers/security/gather.d.ts +28 -5
  63. package/dist/analyzers/security/gather.d.ts.map +1 -1
  64. package/dist/analyzers/security/gather.js +87 -135
  65. package/dist/analyzers/security/gather.js.map +1 -1
  66. package/dist/analyzers/security/index.d.ts +1 -1
  67. package/dist/analyzers/security/index.d.ts.map +1 -1
  68. package/dist/analyzers/security/index.js +16 -11
  69. package/dist/analyzers/security/index.js.map +1 -1
  70. package/dist/analyzers/security/report.d.ts +6 -0
  71. package/dist/analyzers/security/report.d.ts.map +1 -0
  72. package/dist/analyzers/security/report.js +118 -0
  73. package/dist/analyzers/security/report.js.map +1 -0
  74. package/dist/analyzers/security/shallow.d.ts +3 -2
  75. package/dist/analyzers/security/shallow.d.ts.map +1 -1
  76. package/dist/analyzers/security/shallow.js +2 -2
  77. package/dist/analyzers/security/shallow.js.map +1 -1
  78. package/dist/analyzers/tests/detailed.js +1 -1
  79. package/dist/analyzers/tests/detailed.js.map +1 -1
  80. package/dist/analyzers/tests/import-graph.d.ts +8 -22
  81. package/dist/analyzers/tests/import-graph.d.ts.map +1 -1
  82. package/dist/analyzers/tests/import-graph.js +22 -189
  83. package/dist/analyzers/tests/import-graph.js.map +1 -1
  84. package/dist/analyzers/tests/index.d.ts +1 -1
  85. package/dist/analyzers/tests/index.d.ts.map +1 -1
  86. package/dist/analyzers/tests/index.js +3 -3
  87. package/dist/analyzers/tests/index.js.map +1 -1
  88. package/dist/analyzers/tests/shallow.d.ts +3 -2
  89. package/dist/analyzers/tests/shallow.d.ts.map +1 -1
  90. package/dist/analyzers/tests/shallow.js +2 -2
  91. package/dist/analyzers/tests/shallow.js.map +1 -1
  92. package/dist/analyzers/tools/coverage.d.ts +21 -11
  93. package/dist/analyzers/tools/coverage.d.ts.map +1 -1
  94. package/dist/analyzers/tools/coverage.js +32 -44
  95. package/dist/analyzers/tools/coverage.js.map +1 -1
  96. package/dist/analyzers/tools/dotnet.d.ts +8 -0
  97. package/dist/analyzers/tools/dotnet.d.ts.map +1 -0
  98. package/dist/analyzers/tools/dotnet.js +81 -0
  99. package/dist/analyzers/tools/dotnet.js.map +1 -0
  100. package/dist/analyzers/tools/gather-cache.d.ts +16 -0
  101. package/dist/analyzers/tools/gather-cache.d.ts.map +1 -0
  102. package/dist/analyzers/tools/gather-cache.js +126 -0
  103. package/dist/analyzers/tools/gather-cache.js.map +1 -0
  104. package/dist/analyzers/tools/generic.d.ts.map +1 -1
  105. package/dist/analyzers/tools/generic.js +6 -28
  106. package/dist/analyzers/tools/generic.js.map +1 -1
  107. package/dist/analyzers/tools/gitleaks.d.ts +28 -5
  108. package/dist/analyzers/tools/gitleaks.d.ts.map +1 -1
  109. package/dist/analyzers/tools/gitleaks.js +91 -37
  110. package/dist/analyzers/tools/gitleaks.js.map +1 -1
  111. package/dist/analyzers/tools/go.d.ts +8 -0
  112. package/dist/analyzers/tools/go.d.ts.map +1 -0
  113. package/dist/analyzers/tools/go.js +84 -0
  114. package/dist/analyzers/tools/go.js.map +1 -0
  115. package/dist/analyzers/tools/graphify.d.ts +31 -3
  116. package/dist/analyzers/tools/graphify.d.ts.map +1 -1
  117. package/dist/analyzers/tools/graphify.js +78 -36
  118. package/dist/analyzers/tools/graphify.js.map +1 -1
  119. package/dist/analyzers/tools/grep-secrets.d.ts +6 -0
  120. package/dist/analyzers/tools/grep-secrets.d.ts.map +1 -0
  121. package/dist/analyzers/tools/grep-secrets.js +124 -0
  122. package/dist/analyzers/tools/grep-secrets.js.map +1 -0
  123. package/dist/analyzers/tools/jscpd.d.ts +40 -0
  124. package/dist/analyzers/tools/jscpd.d.ts.map +1 -0
  125. package/dist/analyzers/tools/jscpd.js +96 -0
  126. package/dist/analyzers/tools/jscpd.js.map +1 -0
  127. package/dist/analyzers/tools/node.d.ts +8 -0
  128. package/dist/analyzers/tools/node.d.ts.map +1 -0
  129. package/dist/analyzers/tools/node.js +160 -0
  130. package/dist/analyzers/tools/node.js.map +1 -0
  131. package/dist/analyzers/tools/package-json.d.ts +6 -0
  132. package/dist/analyzers/tools/package-json.d.ts.map +1 -0
  133. package/dist/analyzers/tools/package-json.js +67 -0
  134. package/dist/analyzers/tools/package-json.js.map +1 -0
  135. package/dist/analyzers/tools/parallel.d.ts +22 -5
  136. package/dist/analyzers/tools/parallel.d.ts.map +1 -1
  137. package/dist/analyzers/tools/parallel.js +26 -185
  138. package/dist/analyzers/tools/parallel.js.map +1 -1
  139. package/dist/analyzers/tools/paths.d.ts +21 -0
  140. package/dist/analyzers/tools/paths.d.ts.map +1 -0
  141. package/dist/analyzers/tools/paths.js +62 -0
  142. package/dist/analyzers/tools/paths.js.map +1 -0
  143. package/dist/analyzers/tools/python.d.ts +8 -0
  144. package/dist/analyzers/tools/python.d.ts.map +1 -0
  145. package/dist/analyzers/tools/python.js +81 -0
  146. package/dist/analyzers/tools/python.js.map +1 -0
  147. package/dist/analyzers/tools/rust.d.ts +8 -0
  148. package/dist/analyzers/tools/rust.d.ts.map +1 -0
  149. package/dist/analyzers/tools/rust.js +86 -0
  150. package/dist/analyzers/tools/rust.js.map +1 -0
  151. package/dist/analyzers/tools/semgrep.d.ts +39 -0
  152. package/dist/analyzers/tools/semgrep.d.ts.map +1 -0
  153. package/dist/analyzers/tools/semgrep.js +129 -0
  154. package/dist/analyzers/tools/semgrep.js.map +1 -0
  155. package/dist/analyzers/tools/tool-registry.d.ts +0 -41
  156. package/dist/analyzers/tools/tool-registry.d.ts.map +1 -1
  157. package/dist/analyzers/tools/tool-registry.js +0 -87
  158. package/dist/analyzers/tools/tool-registry.js.map +1 -1
  159. package/dist/analyzers/types.d.ts +42 -30
  160. package/dist/analyzers/types.d.ts.map +1 -1
  161. package/dist/cli.js +2 -2
  162. package/dist/cli.js.map +1 -1
  163. package/dist/constants.d.ts +1 -3
  164. package/dist/constants.d.ts.map +1 -1
  165. package/dist/constants.js +55 -14
  166. package/dist/constants.js.map +1 -1
  167. package/dist/languages/capabilities/descriptors.d.ts +74 -0
  168. package/dist/languages/capabilities/descriptors.d.ts.map +1 -0
  169. package/dist/languages/capabilities/descriptors.js +250 -0
  170. package/dist/languages/capabilities/descriptors.js.map +1 -0
  171. package/dist/languages/capabilities/global.d.ts +43 -0
  172. package/dist/languages/capabilities/global.d.ts.map +1 -0
  173. package/dist/languages/capabilities/global.js +48 -0
  174. package/dist/languages/capabilities/global.js.map +1 -0
  175. package/dist/languages/capabilities/index.d.ts +31 -0
  176. package/dist/languages/capabilities/index.d.ts.map +1 -0
  177. package/dist/languages/capabilities/index.js +56 -0
  178. package/dist/languages/capabilities/index.js.map +1 -0
  179. package/dist/languages/capabilities/provider.d.ts +16 -0
  180. package/dist/languages/capabilities/provider.d.ts.map +1 -0
  181. package/dist/languages/capabilities/provider.js +12 -0
  182. package/dist/languages/capabilities/provider.js.map +1 -0
  183. package/dist/languages/capabilities/types.d.ts +226 -0
  184. package/dist/languages/capabilities/types.d.ts.map +1 -0
  185. package/dist/languages/capabilities/types.js +23 -0
  186. package/dist/languages/capabilities/types.js.map +1 -0
  187. package/dist/languages/csharp.d.ts +8 -0
  188. package/dist/languages/csharp.d.ts.map +1 -1
  189. package/dist/languages/csharp.js +203 -103
  190. package/dist/languages/csharp.js.map +1 -1
  191. package/dist/languages/go.d.ts +13 -7
  192. package/dist/languages/go.d.ts.map +1 -1
  193. package/dist/languages/go.js +277 -183
  194. package/dist/languages/go.js.map +1 -1
  195. package/dist/languages/python.d.ts +14 -0
  196. package/dist/languages/python.d.ts.map +1 -1
  197. package/dist/languages/python.js +276 -169
  198. package/dist/languages/python.js.map +1 -1
  199. package/dist/languages/rust.d.ts +8 -0
  200. package/dist/languages/rust.d.ts.map +1 -1
  201. package/dist/languages/rust.js +218 -131
  202. package/dist/languages/rust.js.map +1 -1
  203. package/dist/languages/types.d.ts +16 -15
  204. package/dist/languages/types.d.ts.map +1 -1
  205. package/dist/languages/typescript.d.ts +12 -11
  206. package/dist/languages/typescript.d.ts.map +1 -1
  207. package/dist/languages/typescript.js +256 -161
  208. package/dist/languages/typescript.js.map +1 -1
  209. package/package.json +1 -1
  210. package/templates/.ai/templates/session-checkpoint-template.md +97 -0
@@ -0,0 +1,226 @@
1
+ /**
2
+ * Capability result envelopes.
3
+ *
4
+ * Phase 10e introduces a capabilities model: language packs (and global
5
+ * gatherers) expose typed *capabilities* that the dispatcher collects,
6
+ * runs, and aggregates. Each capability returns a strongly-typed envelope
7
+ * that extends `CapabilityEnvelope` so every result carries:
8
+ *
9
+ * - `schemaVersion`: pinned literal so downstream consumers can detect
10
+ * wire-format changes without inspecting fields.
11
+ * - `tool`: which underlying tool produced this result. Required for
12
+ * attribution in reports and for the `toolsUsed` aggregation.
13
+ *
14
+ * `ImportsResult` landed in Phase 10e.B.4 — a pack pre-computes the full
15
+ * per-pack import graph (extracted specifiers + resolved edges) for every
16
+ * source file matching its `sourceExtensions`, and the dispatcher unions
17
+ * the per-pack graphs so `buildReachable` can BFS over the unified edge
18
+ * map. Global-gatherer envelopes (`SecretsResult`, `CodePatternsResult`,
19
+ * ...) land in Phase 10e.B.6+.
20
+ */
21
+ import type { Coverage } from '../../analyzers/tools/coverage';
22
+ /** Four-tier severity counts, the project-wide convention. */
23
+ export interface SeverityCounts {
24
+ critical: number;
25
+ high: number;
26
+ medium: number;
27
+ low: number;
28
+ }
29
+ /** Common shape every capability envelope carries. */
30
+ export interface CapabilityEnvelope {
31
+ /** Pinned literal — bump when the shape changes incompatibly. */
32
+ readonly schemaVersion: 1;
33
+ /** Underlying tool name (e.g. 'pip-audit', 'eslint', 'govulncheck'). */
34
+ readonly tool: string;
35
+ }
36
+ /** Per-finding detail for dep-vuln reports that need more than counts. */
37
+ export interface DepVulnFinding {
38
+ id: string;
39
+ package: string;
40
+ installedVersion?: string;
41
+ fixedVersion?: string;
42
+ severity: keyof SeverityCounts;
43
+ source: 'osv.dev' | 'tool-default' | 'tool-reported';
44
+ }
45
+ /** Dependency vulnerabilities, the depVulns capability. */
46
+ export interface DepVulnResult extends CapabilityEnvelope {
47
+ /** Severity-tier counts. Always populated; zeros allowed. */
48
+ counts: SeverityCounts;
49
+ /** Source of severity classification, when enrichment is involved. */
50
+ enrichment: 'osv.dev' | null;
51
+ /** Optional per-finding detail. Deep-mode reports populate this. */
52
+ findings?: DepVulnFinding[];
53
+ }
54
+ /** Lint output, the lint capability. Tier counts collapse to errors/warnings in legacy fields. */
55
+ export interface LintResult extends CapabilityEnvelope {
56
+ counts: SeverityCounts;
57
+ }
58
+ /** Coverage data, the coverage capability. Wraps the existing Coverage type. */
59
+ export interface CoverageResult extends CapabilityEnvelope {
60
+ coverage: Coverage;
61
+ }
62
+ /** Detected test runner, the testFramework capability. */
63
+ export interface TestFrameworkResult extends CapabilityEnvelope {
64
+ /** Lower-case framework id: 'vitest', 'jest', 'pytest', 'go-test', 'cargo-test', 'dotnet-test'. */
65
+ name: string;
66
+ }
67
+ /**
68
+ * Pre-computed import graph for one language pack, the imports capability.
69
+ *
70
+ * Every key in `extracted` and `edges` is a project-relative source file
71
+ * path matching one of `sourceExtensions`. Keys are disjoint across packs
72
+ * (a pack only owns files whose extension it declares), so the descriptor
73
+ * aggregates by plain union.
74
+ *
75
+ * `extracted` carries the raw specifiers captured from each file (e.g.
76
+ * `'./foo'`, `'lodash'`, `'../bar/baz'`). `edges` carries only the
77
+ * specifiers the pack could resolve to an in-project file; external
78
+ * packages and unresolvable specifiers are dropped. `buildReachable`
79
+ * consumes `edges`; future analyses (unused-imports, dead-code) can
80
+ * consume `extracted` without re-parsing source.
81
+ *
82
+ * Packs whose language has no file-based import resolution (Rust uses
83
+ * `mod`/crate paths, C# uses namespaces) still emit a result: `extracted`
84
+ * is populated for completeness and `edges` is empty. The union of an
85
+ * empty edges map is a no-op.
86
+ */
87
+ export interface ImportsResult extends CapabilityEnvelope {
88
+ readonly sourceExtensions: ReadonlyArray<string>;
89
+ readonly extracted: ReadonlyMap<string, ReadonlyArray<string>>;
90
+ readonly edges: ReadonlyMap<string, ReadonlySet<string>>;
91
+ }
92
+ /** Per-finding detail for the secrets capability. */
93
+ export interface SecretFinding {
94
+ file: string;
95
+ line: number;
96
+ rule: string;
97
+ severity: keyof SeverityCounts;
98
+ /** Human-readable description from the scanner (e.g. gitleaks' `Description` field). */
99
+ title?: string;
100
+ }
101
+ /**
102
+ * Hardcoded-secret findings, the secrets capability. Produced by global
103
+ * scanners (gitleaks today, trufflehog-compatible in the future) that
104
+ * run once per repo rather than per language pack. `suppressedCount`
105
+ * is the count of findings the repo's `.dxkit-suppressions.json`
106
+ * acknowledged and dropped — reported separately so the UI can
107
+ * distinguish "zero findings" from "zero visible findings after
108
+ * suppression."
109
+ */
110
+ export interface SecretsResult extends CapabilityEnvelope {
111
+ findings: ReadonlyArray<SecretFinding>;
112
+ suppressedCount: number;
113
+ }
114
+ /** Per-finding detail for the codePatterns capability. */
115
+ export interface CodePatternFinding {
116
+ file: string;
117
+ line: number;
118
+ rule: string;
119
+ severity: keyof SeverityCounts;
120
+ /** Human-readable summary from the scanner (first line of semgrep's `message`). */
121
+ title: string;
122
+ /** CWE identifier when the scanner supplies one (e.g. `CWE-79`). Empty otherwise. */
123
+ cwe: string;
124
+ }
125
+ /**
126
+ * Code-pattern findings, the codePatterns capability. Produced by static
127
+ * analysis scanners (semgrep today) that consume rulesets per active
128
+ * language pack (`LanguageSupport.semgrepRulesets`). Running once per
129
+ * repo rather than per pack: the scanner takes a union of rulesets and
130
+ * emits findings attributed by file path.
131
+ *
132
+ * `suppressedCount` mirrors `SecretsResult` — the count dropped by
133
+ * `.dxkit-suppressions.json` so the UI can report "zero visible after
134
+ * suppression" separately from "zero real findings."
135
+ */
136
+ export interface CodePatternsResult extends CapabilityEnvelope {
137
+ findings: ReadonlyArray<CodePatternFinding>;
138
+ suppressedCount: number;
139
+ }
140
+ /** One side of a duplicate block reported by a clone detector. */
141
+ export interface DuplicationCloneSide {
142
+ file: string;
143
+ startLine: number;
144
+ endLine: number;
145
+ }
146
+ /** A single clone pair (two locations with matching content). */
147
+ export interface DuplicationClone {
148
+ lines: number;
149
+ tokens: number;
150
+ a: DuplicationCloneSide;
151
+ b: DuplicationCloneSide;
152
+ }
153
+ /**
154
+ * Duplication metrics, the duplication capability. Produced by clone
155
+ * detectors (jscpd today) that tokenize every source file and emit
156
+ * pair-wise matches above configured thresholds. `topClones` is
157
+ * bounded (the detector sorts + truncates) so the envelope is safe
158
+ * to keep in reports.
159
+ */
160
+ export interface DuplicationResult extends CapabilityEnvelope {
161
+ totalLines: number;
162
+ duplicatedLines: number;
163
+ /** Rounded to 2 decimal places. */
164
+ percentage: number;
165
+ /** Total clone pairs found (may exceed topClones.length after truncation). */
166
+ cloneCount: number;
167
+ /** Largest clone pairs first; typically capped at ~15. */
168
+ topClones: ReadonlyArray<DuplicationClone>;
169
+ }
170
+ /**
171
+ * Structural metrics, the structural capability. Produced by AST
172
+ * graph-builders (graphify today) that walk every source file via
173
+ * tree-sitter, build a call-graph, detect communities, and derive
174
+ * cohesion / dead-import / orphan signals.
175
+ *
176
+ * Every field is a repo-level scalar produced by one graph pass —
177
+ * summing them across providers would double-count the same real
178
+ * functions/modules, so the descriptor aggregate is last-wins
179
+ * (matches COVERAGE's strategy for the same reason).
180
+ */
181
+ export interface StructuralResult extends CapabilityEnvelope {
182
+ functionCount: number;
183
+ classCount: number;
184
+ maxFunctionsInFile: number;
185
+ maxFunctionsFilePath: string;
186
+ godNodeCount: number;
187
+ communityCount: number;
188
+ /** Mean cohesion score across communities, 0-1 range, 3 decimal places. */
189
+ avgCohesion: number;
190
+ orphanModuleCount: number;
191
+ deadImportCount: number;
192
+ /** Share of source files with zero AST nodes — proxy for "mostly-commented" files. */
193
+ commentedCodeRatio: number;
194
+ }
195
+ /**
196
+ * Internal outcome shape used by language packs' `gatherDepVulnsResult`
197
+ * helpers. The pack's `capabilities.depVulns` provider unwraps the
198
+ * envelope (returning null for every non-success kind) so the dispatcher
199
+ * surface stays `T | null`; keeping the richer outcome here lets the
200
+ * pack's own code distinguish e.g. "tool missing" from "tool ran but
201
+ * produced no output" if a future caller needs that detail.
202
+ */
203
+ export type DepVulnGatherOutcome = {
204
+ kind: 'success';
205
+ envelope: DepVulnResult;
206
+ } | {
207
+ kind: 'tool-missing';
208
+ } | {
209
+ kind: 'parse-error';
210
+ } | {
211
+ kind: 'no-output';
212
+ };
213
+ /**
214
+ * Internal outcome shape for the lint capability. Simpler than depVulns:
215
+ * either the linter ran and we have tier counts, or it didn't and we
216
+ * have a reason. The pack's `capabilities.lint` provider unwraps
217
+ * `success` into the envelope and returns null otherwise.
218
+ */
219
+ export type LintGatherOutcome = {
220
+ kind: 'success';
221
+ envelope: LintResult;
222
+ } | {
223
+ kind: 'unavailable';
224
+ reason: string;
225
+ };
226
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/languages/capabilities/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ /**
3
+ * Capability result envelopes.
4
+ *
5
+ * Phase 10e introduces a capabilities model: language packs (and global
6
+ * gatherers) expose typed *capabilities* that the dispatcher collects,
7
+ * runs, and aggregates. Each capability returns a strongly-typed envelope
8
+ * that extends `CapabilityEnvelope` so every result carries:
9
+ *
10
+ * - `schemaVersion`: pinned literal so downstream consumers can detect
11
+ * wire-format changes without inspecting fields.
12
+ * - `tool`: which underlying tool produced this result. Required for
13
+ * attribution in reports and for the `toolsUsed` aggregation.
14
+ *
15
+ * `ImportsResult` landed in Phase 10e.B.4 — a pack pre-computes the full
16
+ * per-pack import graph (extracted specifiers + resolved edges) for every
17
+ * source file matching its `sourceExtensions`, and the dispatcher unions
18
+ * the per-pack graphs so `buildReachable` can BFS over the unified edge
19
+ * map. Global-gatherer envelopes (`SecretsResult`, `CodePatternsResult`,
20
+ * ...) land in Phase 10e.B.6+.
21
+ */
22
+ Object.defineProperty(exports, "__esModule", { value: true });
23
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/languages/capabilities/types.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;GAmBG"}
@@ -1,5 +1,13 @@
1
1
  import type { Coverage } from '../analyzers/tools/coverage';
2
2
  import type { LanguageSupport } from './types';
3
3
  export declare function parseCoberturaXml(raw: string, sourceFile: string, cwd: string): Coverage | null;
4
+ /**
5
+ * Capture C# `using` directives from source text, including
6
+ * `using static Foo`, aliased (`using X = Foo.Bar`), and plain forms.
7
+ * C# has no deterministic file-level resolver (namespaces aren't files),
8
+ * so this is the only raw helper the imports capability needs. Exported
9
+ * for unit tests.
10
+ */
11
+ export declare function extractCsharpImportsRaw(content: string): string[];
4
12
  export declare const csharp: LanguageSupport;
5
13
  //# sourceMappingURL=csharp.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"csharp.d.ts","sourceRoot":"","sources":["../../src/languages/csharp.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAgB,MAAM,6BAA6B,CAAC;AAI1E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAwD/C,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAoC/F;AAED,eAAO,MAAM,MAAM,EAAE,eAoJpB,CAAC"}
1
+ {"version":3,"file":"csharp.d.ts","sourceRoot":"","sources":["../../src/languages/csharp.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAgB,MAAM,6BAA6B,CAAC;AAc1E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAwD/C,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAoC/F;AA+HD;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAQjE;AAqED,eAAO,MAAM,MAAM,EAAE,eAqCpB,CAAC"}
@@ -35,8 +35,10 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.csharp = void 0;
37
37
  exports.parseCoberturaXml = parseCoberturaXml;
38
+ exports.extractCsharpImportsRaw = extractCsharpImportsRaw;
38
39
  const fs = __importStar(require("fs"));
39
40
  const path = __importStar(require("path"));
41
+ const exclusions_1 = require("../analyzers/tools/exclusions");
40
42
  const runner_1 = require("../analyzers/tools/runner");
41
43
  const tool_registry_1 = require("../analyzers/tools/tool-registry");
42
44
  function dirHasMatching(dir, regex) {
@@ -133,6 +135,201 @@ function parseCoberturaXml(raw, sourceFile, cwd) {
133
135
  const rel = path.relative(cwd, path.resolve(cwd, sourceFile)).split(path.sep).join('/');
134
136
  return { source: 'cobertura', sourceFile: rel || sourceFile, linePercent, files };
135
137
  }
138
+ /**
139
+ * Single source of truth for the csharp pack's dep-vuln gathering.
140
+ * Consumed by `csharpDepVulnsProvider` (capability dispatcher). Runs
141
+ * independently of `dotnet-format` availability — historical bug where
142
+ * projects with `dotnet` but no `dotnet-format` saw zero vuln data.
143
+ */
144
+ async function gatherCsharpDepVulnsResult(cwd) {
145
+ const vulnRaw = (0, runner_1.run)('dotnet list package --vulnerable --format json 2>/dev/null', cwd, 120000);
146
+ if (!vulnRaw)
147
+ return { kind: 'no-output' };
148
+ try {
149
+ const data = JSON.parse(vulnRaw);
150
+ let critical = 0;
151
+ let high = 0;
152
+ let medium = 0;
153
+ let low = 0;
154
+ for (const proj of data.projects || []) {
155
+ for (const fw of proj.frameworks || []) {
156
+ for (const pkg of fw.topLevelPackages || []) {
157
+ for (const adv of pkg.advisories || []) {
158
+ const sev = adv.severity?.toLowerCase();
159
+ if (sev === 'critical')
160
+ critical++;
161
+ else if (sev === 'high')
162
+ high++;
163
+ else if (sev === 'moderate' || sev === 'medium')
164
+ medium++;
165
+ else
166
+ low++;
167
+ }
168
+ }
169
+ }
170
+ }
171
+ if (critical + high + medium + low === 0)
172
+ return { kind: 'no-output' };
173
+ const envelope = {
174
+ schemaVersion: 1,
175
+ tool: 'dotnet-vulnerable',
176
+ enrichment: null,
177
+ counts: { critical, high, medium, low },
178
+ };
179
+ return { kind: 'success', envelope };
180
+ }
181
+ catch {
182
+ return { kind: 'parse-error' };
183
+ }
184
+ }
185
+ const csharpDepVulnsProvider = {
186
+ source: 'csharp',
187
+ async gather(cwd) {
188
+ const outcome = await gatherCsharpDepVulnsResult(cwd);
189
+ return outcome.kind === 'success' ? outcome.envelope : null;
190
+ },
191
+ };
192
+ /**
193
+ * Single source of truth for the csharp pack's lint gathering.
194
+ * Consumed by `csharpLintProvider` (capability dispatcher).
195
+ *
196
+ * dotnet-format is a formatter, not a tiered linter — it emits binary
197
+ * pass/fail per file. Violations are formatting issues (indentation,
198
+ * spacing), not correctness. This helper reports them at `low` tier so
199
+ * they don't inflate the Quality/Slop score.
200
+ */
201
+ function gatherCsharpLintResult(cwd) {
202
+ const dotnet = (0, tool_registry_1.findTool)(tool_registry_1.TOOL_DEFS['dotnet-format'], cwd);
203
+ if (!dotnet.available) {
204
+ return { kind: 'unavailable', reason: 'not installed' };
205
+ }
206
+ const exitCode = (0, runner_1.runExitCode)('dotnet format --verify-no-changes 2>/dev/null', cwd, 120000);
207
+ let violations = 0;
208
+ if (exitCode !== 0) {
209
+ const raw = (0, runner_1.run)('dotnet format --verify-no-changes 2>&1', cwd, 120000);
210
+ violations = raw ? raw.split('\n').filter((l) => l.includes('Formatted')).length : 1;
211
+ }
212
+ const envelope = {
213
+ schemaVersion: 1,
214
+ tool: 'dotnet-format',
215
+ counts: { critical: 0, high: 0, medium: 0, low: violations },
216
+ };
217
+ return { kind: 'success', envelope };
218
+ }
219
+ const csharpLintProvider = {
220
+ source: 'csharp',
221
+ async gather(cwd) {
222
+ const outcome = gatherCsharpLintResult(cwd);
223
+ return outcome.kind === 'success' ? outcome.envelope : null;
224
+ },
225
+ };
226
+ /**
227
+ * Single source of truth for the csharp pack's coverage gathering.
228
+ * Locates the Cobertura artifact across known layouts (explicit `coverage/`
229
+ * dir or `dotnet test --collect`'s TestResults/<guid>/ subtree). Consumed
230
+ * by `csharpCoverageProvider` (capability dispatcher).
231
+ */
232
+ function gatherCsharpCoverageResult(cwd) {
233
+ const artifact = findCoberturaArtifact(cwd);
234
+ if (!artifact)
235
+ return null;
236
+ let raw;
237
+ try {
238
+ raw = fs.readFileSync(artifact, 'utf-8');
239
+ }
240
+ catch {
241
+ return null;
242
+ }
243
+ const rel = path.relative(cwd, artifact).split(path.sep).join('/');
244
+ const coverage = parseCoberturaXml(raw, rel, cwd);
245
+ if (!coverage)
246
+ return null;
247
+ return { schemaVersion: 1, tool: `coverage:${coverage.source}`, coverage };
248
+ }
249
+ const csharpCoverageProvider = {
250
+ source: 'csharp',
251
+ async gather(cwd) {
252
+ return gatherCsharpCoverageResult(cwd);
253
+ },
254
+ };
255
+ /**
256
+ * Capture C# `using` directives from source text, including
257
+ * `using static Foo`, aliased (`using X = Foo.Bar`), and plain forms.
258
+ * C# has no deterministic file-level resolver (namespaces aren't files),
259
+ * so this is the only raw helper the imports capability needs. Exported
260
+ * for unit tests.
261
+ */
262
+ function extractCsharpImportsRaw(content) {
263
+ const out = [];
264
+ const re = /^\s*using\s+(?:static\s+)?(?:[A-Za-z_]\w*\s*=\s*)?([A-Za-z_][\w.]*)\s*;/gm;
265
+ let m;
266
+ while ((m = re.exec(content)) !== null) {
267
+ out.push(m[1]);
268
+ }
269
+ return out;
270
+ }
271
+ /**
272
+ * Enumerate .cs source files and capture the pack's per-file imports.
273
+ * C# has no `resolveImport` (namespaces don't map to file paths
274
+ * deterministically), so `edges` is always empty.
275
+ */
276
+ function gatherCsharpImportsResult(cwd) {
277
+ const excludes = (0, exclusions_1.getFindExcludeFlags)(cwd);
278
+ const raw = (0, runner_1.run)(`find . -type f -name "*.cs" ${excludes} 2>/dev/null`, cwd);
279
+ if (!raw)
280
+ return null;
281
+ const extracted = new Map();
282
+ for (const line of raw.split('\n')) {
283
+ const p = line.trim();
284
+ if (!p)
285
+ continue;
286
+ const rel = p.replace(/^\.\//, '');
287
+ let content;
288
+ try {
289
+ content = fs.readFileSync(path.join(cwd, rel), 'utf-8');
290
+ }
291
+ catch {
292
+ continue;
293
+ }
294
+ extracted.set(rel, extractCsharpImportsRaw(content));
295
+ }
296
+ if (extracted.size === 0)
297
+ return null;
298
+ return {
299
+ schemaVersion: 1,
300
+ tool: 'csharp-imports',
301
+ sourceExtensions: ['.cs'],
302
+ extracted,
303
+ edges: new Map(),
304
+ };
305
+ }
306
+ const csharpImportsProvider = {
307
+ source: 'csharp',
308
+ async gather(cwd) {
309
+ return gatherCsharpImportsResult(cwd);
310
+ },
311
+ };
312
+ /**
313
+ * Detect C# test projects by the runner package referenced in the
314
+ * project's `.csproj` file — xunit, NUnit, and MSTest cover the
315
+ * dominant majority of .NET test projects. A repo without any
316
+ * `.csproj` referencing these returns null.
317
+ */
318
+ function gatherCsharpTestFrameworkResult(cwd) {
319
+ const hasCsproj = (0, runner_1.fileExists)(cwd, '*.csproj') || !!findMatchingRecursive(cwd, /\.csproj$/, 3);
320
+ if (!hasCsproj)
321
+ return null;
322
+ const csproj = (0, runner_1.run)("find . -name '*.csproj' -exec grep -l 'xunit\\|nunit\\|MSTest' {} \\; 2>/dev/null | head -1", cwd);
323
+ if (!csproj)
324
+ return null;
325
+ return { schemaVersion: 1, tool: 'csharp', name: 'dotnet-test' };
326
+ }
327
+ const csharpTestFrameworkProvider = {
328
+ source: 'csharp',
329
+ async gather(cwd) {
330
+ return gatherCsharpTestFrameworkResult(cwd);
331
+ },
332
+ };
136
333
  exports.csharp = {
137
334
  id: 'csharp',
138
335
  displayName: 'C#',
@@ -147,35 +344,13 @@ exports.csharp = {
147
344
  tools: ['dotnet-format'],
148
345
  // p/csharp semgrep ruleset is sparse — skip until it matures.
149
346
  semgrepRulesets: [],
150
- parseCoverage(cwd) {
151
- const artifact = findCoberturaArtifact(cwd);
152
- if (!artifact)
153
- return null;
154
- let raw;
155
- try {
156
- raw = fs.readFileSync(artifact, 'utf-8');
157
- }
158
- catch {
159
- return null;
160
- }
161
- const rel = path.relative(cwd, artifact).split(path.sep).join('/');
162
- return parseCoberturaXml(raw, rel, cwd);
347
+ capabilities: {
348
+ depVulns: csharpDepVulnsProvider,
349
+ lint: csharpLintProvider,
350
+ coverage: csharpCoverageProvider,
351
+ imports: csharpImportsProvider,
352
+ testFramework: csharpTestFrameworkProvider,
163
353
  },
164
- extractImports(content) {
165
- // `using System;`, `using System.IO;`, `using static System.Math;`,
166
- // `using Alias = Foo.Bar;`. Captures the fully-qualified namespace.
167
- const out = [];
168
- const re = /^\s*using\s+(?:static\s+)?(?:[A-Za-z_]\w*\s*=\s*)?([A-Za-z_][\w.]*)\s*;/gm;
169
- let m;
170
- while ((m = re.exec(content)) !== null) {
171
- out.push(m[1]);
172
- }
173
- return out;
174
- },
175
- // resolveImport intentionally omitted: C# namespaces don't map to file
176
- // paths deterministically — one namespace can span many files, one file
177
- // can declare many namespaces. Internal edges are best inferred via the
178
- // project assembly graph, which is out of scope here.
179
354
  // mapLintSeverity intentionally omitted: dotnet-format is a formatter,
180
355
  // not a tiered linter. It emits binary pass/fail per file and doesn't
181
356
  // expose per-rule codes that could be categorized into
@@ -186,80 +361,5 @@ exports.csharp = {
186
361
  // mapping each to a tier. That's deferred until a C# test project
187
362
  // is available to validate the integration; see architecture-redesign
188
363
  // plan for the capability-based approach this will live in.
189
- async gatherMetrics(cwd) {
190
- const metrics = {
191
- toolsUsed: [],
192
- toolsUnavailable: [],
193
- };
194
- const dotnet = (0, tool_registry_1.findTool)(tool_registry_1.TOOL_DEFS['dotnet-format'], cwd);
195
- if (dotnet.available) {
196
- const exitCode = (0, runner_1.runExitCode)('dotnet format --verify-no-changes 2>/dev/null', cwd, 120000);
197
- if (exitCode === 0) {
198
- metrics.lintErrors = 0;
199
- metrics.lintWarnings = 0;
200
- }
201
- else {
202
- const raw = (0, runner_1.run)('dotnet format --verify-no-changes 2>&1', cwd, 120000);
203
- const violations = raw ? raw.split('\n').filter((l) => l.includes('Formatted')).length : 1;
204
- // dotnet-format findings are formatting violations (indentation,
205
- // spacing) — style issues, not correctness errors. Report them as
206
- // warnings so they don't inflate the "lint errors" count that
207
- // drives Quality/Slop scoring. A future upgrade to parse
208
- // `dotnet build` diagnostics can populate lintErrors properly.
209
- metrics.lintErrors = 0;
210
- metrics.lintWarnings = violations;
211
- }
212
- metrics.lintTool = 'dotnet-format';
213
- metrics.toolsUsed.push('dotnet-format');
214
- const vulnRaw = (0, runner_1.run)('dotnet list package --vulnerable --format json 2>/dev/null', cwd, 120000);
215
- if (vulnRaw) {
216
- try {
217
- const data = JSON.parse(vulnRaw);
218
- let critical = 0;
219
- let high = 0;
220
- let medium = 0;
221
- let low = 0;
222
- for (const proj of data.projects || []) {
223
- for (const fw of proj.frameworks || []) {
224
- for (const pkg of fw.topLevelPackages || []) {
225
- for (const adv of pkg.advisories || []) {
226
- const sev = adv.severity?.toLowerCase();
227
- if (sev === 'critical')
228
- critical++;
229
- else if (sev === 'high')
230
- high++;
231
- else if (sev === 'moderate' || sev === 'medium')
232
- medium++;
233
- else
234
- low++;
235
- }
236
- }
237
- }
238
- }
239
- if (critical + high + medium + low > 0) {
240
- metrics.depVulnCritical = critical;
241
- metrics.depVulnHigh = high;
242
- metrics.depVulnMedium = medium;
243
- metrics.depVulnLow = low;
244
- metrics.depAuditTool = 'dotnet-vulnerable';
245
- metrics.toolsUsed.push('dotnet-vulnerable');
246
- }
247
- }
248
- catch {
249
- metrics.toolsUnavailable.push('dotnet-vulnerable (parse error)');
250
- }
251
- }
252
- }
253
- else {
254
- metrics.toolsUnavailable.push('dotnet-format');
255
- }
256
- if ((0, runner_1.fileExists)(cwd, '*.csproj') || findMatchingRecursive(cwd, /\.csproj$/, 3)) {
257
- const csproj = (0, runner_1.run)("find . -name '*.csproj' -exec grep -l 'xunit\\|nunit\\|MSTest' {} \\; 2>/dev/null | head -1", cwd);
258
- if (csproj) {
259
- metrics.testFramework = 'dotnet-test';
260
- }
261
- }
262
- return metrics;
263
- },
264
364
  };
265
365
  //# sourceMappingURL=csharp.js.map