ghagga-core 2.2.0 → 2.4.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 (173) hide show
  1. package/dist/agents/consensus.d.ts +1 -1
  2. package/dist/agents/consensus.d.ts.map +1 -1
  3. package/dist/agents/consensus.js +7 -5
  4. package/dist/agents/consensus.js.map +1 -1
  5. package/dist/agents/prompts.d.ts.map +1 -1
  6. package/dist/agents/prompts.js +1 -3
  7. package/dist/agents/prompts.js.map +1 -1
  8. package/dist/agents/simple.d.ts +1 -1
  9. package/dist/agents/simple.d.ts.map +1 -1
  10. package/dist/agents/simple.js +12 -17
  11. package/dist/agents/simple.js.map +1 -1
  12. package/dist/agents/workflow.d.ts +1 -1
  13. package/dist/agents/workflow.d.ts.map +1 -1
  14. package/dist/agents/workflow.js +5 -4
  15. package/dist/agents/workflow.js.map +1 -1
  16. package/dist/format.d.ts.map +1 -1
  17. package/dist/format.js +25 -5
  18. package/dist/format.js.map +1 -1
  19. package/dist/index.d.ts +12 -10
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +7 -8
  22. package/dist/index.js.map +1 -1
  23. package/dist/memory/context.d.ts.map +1 -1
  24. package/dist/memory/context.js.map +1 -1
  25. package/dist/memory/engram-client.d.ts.map +1 -1
  26. package/dist/memory/engram-client.js +4 -1
  27. package/dist/memory/engram-client.js.map +1 -1
  28. package/dist/memory/engram-mapping.d.ts +1 -1
  29. package/dist/memory/engram-mapping.d.ts.map +1 -1
  30. package/dist/memory/engram-mapping.js +2 -2
  31. package/dist/memory/engram-mapping.js.map +1 -1
  32. package/dist/memory/engram.d.ts +1 -2
  33. package/dist/memory/engram.d.ts.map +1 -1
  34. package/dist/memory/engram.js +1 -2
  35. package/dist/memory/engram.js.map +1 -1
  36. package/dist/memory/persist.d.ts.map +1 -1
  37. package/dist/memory/persist.js +1 -1
  38. package/dist/memory/persist.js.map +1 -1
  39. package/dist/memory/privacy.d.ts.map +1 -1
  40. package/dist/memory/privacy.js +4 -1
  41. package/dist/memory/privacy.js.map +1 -1
  42. package/dist/memory/search.d.ts +26 -0
  43. package/dist/memory/search.d.ts.map +1 -1
  44. package/dist/memory/search.js +55 -8
  45. package/dist/memory/search.js.map +1 -1
  46. package/dist/memory/sqlite.d.ts +7 -2
  47. package/dist/memory/sqlite.d.ts.map +1 -1
  48. package/dist/memory/sqlite.js +42 -34
  49. package/dist/memory/sqlite.js.map +1 -1
  50. package/dist/pipeline.d.ts.map +1 -1
  51. package/dist/pipeline.js +74 -32
  52. package/dist/pipeline.js.map +1 -1
  53. package/dist/providers/fallback.d.ts.map +1 -1
  54. package/dist/providers/fallback.js +5 -3
  55. package/dist/providers/fallback.js.map +1 -1
  56. package/dist/providers/index.d.ts.map +1 -1
  57. package/dist/providers/index.js +1 -1
  58. package/dist/providers/index.js.map +1 -1
  59. package/dist/tools/budget.d.ts +26 -0
  60. package/dist/tools/budget.d.ts.map +1 -0
  61. package/dist/tools/budget.js +78 -0
  62. package/dist/tools/budget.js.map +1 -0
  63. package/dist/tools/cpd.d.ts +1 -1
  64. package/dist/tools/cpd.d.ts.map +1 -1
  65. package/dist/tools/cpd.js +20 -15
  66. package/dist/tools/cpd.js.map +1 -1
  67. package/dist/tools/execution.d.ts +18 -0
  68. package/dist/tools/execution.d.ts.map +1 -0
  69. package/dist/tools/execution.js +82 -0
  70. package/dist/tools/execution.js.map +1 -0
  71. package/dist/tools/index.d.ts +16 -0
  72. package/dist/tools/index.d.ts.map +1 -0
  73. package/dist/tools/index.js +20 -0
  74. package/dist/tools/index.js.map +1 -0
  75. package/dist/tools/orchestrator.d.ts +24 -0
  76. package/dist/tools/orchestrator.d.ts.map +1 -0
  77. package/dist/tools/orchestrator.js +127 -0
  78. package/dist/tools/orchestrator.js.map +1 -0
  79. package/dist/tools/plugins/bandit.d.ts +22 -0
  80. package/dist/tools/plugins/bandit.d.ts.map +1 -0
  81. package/dist/tools/plugins/bandit.js +79 -0
  82. package/dist/tools/plugins/bandit.js.map +1 -0
  83. package/dist/tools/plugins/biome.d.ts +22 -0
  84. package/dist/tools/plugins/biome.d.ts.map +1 -0
  85. package/dist/tools/plugins/biome.js +80 -0
  86. package/dist/tools/plugins/biome.js.map +1 -0
  87. package/dist/tools/plugins/clippy.d.ts +25 -0
  88. package/dist/tools/plugins/clippy.d.ts.map +1 -0
  89. package/dist/tools/plugins/clippy.js +95 -0
  90. package/dist/tools/plugins/clippy.js.map +1 -0
  91. package/dist/tools/plugins/cpd.d.ts +20 -0
  92. package/dist/tools/plugins/cpd.d.ts.map +1 -0
  93. package/dist/tools/plugins/cpd.js +111 -0
  94. package/dist/tools/plugins/cpd.js.map +1 -0
  95. package/dist/tools/plugins/gitleaks.d.ts +18 -0
  96. package/dist/tools/plugins/gitleaks.d.ts.map +1 -0
  97. package/dist/tools/plugins/gitleaks.js +81 -0
  98. package/dist/tools/plugins/gitleaks.js.map +1 -0
  99. package/dist/tools/plugins/golangci-lint.d.ts +27 -0
  100. package/dist/tools/plugins/golangci-lint.d.ts.map +1 -0
  101. package/dist/tools/plugins/golangci-lint.js +87 -0
  102. package/dist/tools/plugins/golangci-lint.js.map +1 -0
  103. package/dist/tools/plugins/hadolint.d.ts +22 -0
  104. package/dist/tools/plugins/hadolint.d.ts.map +1 -0
  105. package/dist/tools/plugins/hadolint.js +99 -0
  106. package/dist/tools/plugins/hadolint.js.map +1 -0
  107. package/dist/tools/plugins/index.d.ts +37 -0
  108. package/dist/tools/plugins/index.d.ts.map +1 -0
  109. package/dist/tools/plugins/index.js +93 -0
  110. package/dist/tools/plugins/index.js.map +1 -0
  111. package/dist/tools/plugins/lizard.d.ts +24 -0
  112. package/dist/tools/plugins/lizard.d.ts.map +1 -0
  113. package/dist/tools/plugins/lizard.js +83 -0
  114. package/dist/tools/plugins/lizard.js.map +1 -0
  115. package/dist/tools/plugins/markdownlint.d.ts +17 -0
  116. package/dist/tools/plugins/markdownlint.d.ts.map +1 -0
  117. package/dist/tools/plugins/markdownlint.js +70 -0
  118. package/dist/tools/plugins/markdownlint.js.map +1 -0
  119. package/dist/tools/plugins/pmd.d.ts +23 -0
  120. package/dist/tools/plugins/pmd.d.ts.map +1 -0
  121. package/dist/tools/plugins/pmd.js +108 -0
  122. package/dist/tools/plugins/pmd.js.map +1 -0
  123. package/dist/tools/plugins/psalm.d.ts +24 -0
  124. package/dist/tools/plugins/psalm.d.ts.map +1 -0
  125. package/dist/tools/plugins/psalm.js +85 -0
  126. package/dist/tools/plugins/psalm.js.map +1 -0
  127. package/dist/tools/plugins/ruff.d.ts +22 -0
  128. package/dist/tools/plugins/ruff.d.ts.map +1 -0
  129. package/dist/tools/plugins/ruff.js +80 -0
  130. package/dist/tools/plugins/ruff.js.map +1 -0
  131. package/dist/tools/plugins/semgrep.d.ts +23 -0
  132. package/dist/tools/plugins/semgrep.d.ts.map +1 -0
  133. package/dist/tools/plugins/semgrep.js +82 -0
  134. package/dist/tools/plugins/semgrep.js.map +1 -0
  135. package/dist/tools/plugins/shellcheck.d.ts +23 -0
  136. package/dist/tools/plugins/shellcheck.d.ts.map +1 -0
  137. package/dist/tools/plugins/shellcheck.js +87 -0
  138. package/dist/tools/plugins/shellcheck.js.map +1 -0
  139. package/dist/tools/plugins/trivy.d.ts +25 -0
  140. package/dist/tools/plugins/trivy.d.ts.map +1 -0
  141. package/dist/tools/plugins/trivy.js +108 -0
  142. package/dist/tools/plugins/trivy.js.map +1 -0
  143. package/dist/tools/registry.d.ts +37 -0
  144. package/dist/tools/registry.d.ts.map +1 -0
  145. package/dist/tools/registry.js +61 -0
  146. package/dist/tools/registry.js.map +1 -0
  147. package/dist/tools/resolve.d.ts +37 -0
  148. package/dist/tools/resolve.d.ts.map +1 -0
  149. package/dist/tools/resolve.js +67 -0
  150. package/dist/tools/resolve.js.map +1 -0
  151. package/dist/tools/runner.d.ts +16 -2
  152. package/dist/tools/runner.d.ts.map +1 -1
  153. package/dist/tools/runner.js +78 -10
  154. package/dist/tools/runner.js.map +1 -1
  155. package/dist/tools/semgrep.d.ts +1 -1
  156. package/dist/tools/semgrep.d.ts.map +1 -1
  157. package/dist/tools/semgrep.js +20 -14
  158. package/dist/tools/semgrep.js.map +1 -1
  159. package/dist/tools/trivy.d.ts +1 -1
  160. package/dist/tools/trivy.d.ts.map +1 -1
  161. package/dist/tools/trivy.js +3 -1
  162. package/dist/tools/trivy.js.map +1 -1
  163. package/dist/tools/types.d.ts +83 -0
  164. package/dist/tools/types.d.ts.map +1 -0
  165. package/dist/tools/types.js +11 -0
  166. package/dist/tools/types.js.map +1 -0
  167. package/dist/types.d.ts +15 -3
  168. package/dist/types.d.ts.map +1 -1
  169. package/dist/types.js +2 -0
  170. package/dist/types.js.map +1 -1
  171. package/dist/utils/diff.js +1 -1
  172. package/dist/utils/diff.js.map +1 -1
  173. package/package.json +7 -7
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Semgrep plugin — security analysis (always-on).
3
+ *
4
+ * Adapted from:
5
+ * - packages/core/src/tools/semgrep.ts (parsing logic)
6
+ * - apps/action/src/tools/semgrep.ts (install/run flow)
7
+ *
8
+ * Uses ExecutionContext for DI instead of direct child_process.
9
+ */
10
+ const SEMGREP_VERSION = '1.90.0';
11
+ /**
12
+ * Map Semgrep severity to GHAGGA FindingSeverity.
13
+ * ERROR -> high, WARNING -> medium, INFO -> info, default -> low
14
+ */
15
+ export function mapSemgrepSeverity(semgrepSeverity) {
16
+ switch (semgrepSeverity.toUpperCase()) {
17
+ case 'ERROR':
18
+ return 'high';
19
+ case 'WARNING':
20
+ return 'medium';
21
+ case 'INFO':
22
+ return 'info';
23
+ default:
24
+ return 'low';
25
+ }
26
+ }
27
+ /**
28
+ * Parse Semgrep JSON output into ReviewFinding[].
29
+ * Exported for direct testing with fixture data.
30
+ */
31
+ export function parseSemgrepOutput(raw, repoDir) {
32
+ if (raw.timedOut)
33
+ return [];
34
+ try {
35
+ const result = JSON.parse(raw.stdout);
36
+ return (result.results ?? []).map((r) => ({
37
+ severity: mapSemgrepSeverity(r.extra.severity),
38
+ category: 'security',
39
+ file: r.path.replace(`${repoDir}/`, ''),
40
+ line: r.start.line,
41
+ message: r.extra.message,
42
+ source: 'semgrep',
43
+ }));
44
+ }
45
+ catch {
46
+ return [];
47
+ }
48
+ }
49
+ export const semgrepPlugin = {
50
+ name: 'semgrep',
51
+ displayName: 'Semgrep',
52
+ category: 'security',
53
+ tier: 'always-on',
54
+ version: SEMGREP_VERSION,
55
+ outputFormat: 'json',
56
+ cachePaths: ['/usr/local/bin/semgrep'],
57
+ async install(ctx) {
58
+ const cached = await ctx.cacheRestore('semgrep', ['/usr/local/bin/semgrep']);
59
+ if (cached) {
60
+ try {
61
+ await ctx.exec('semgrep', ['--version'], { timeoutMs: 10_000 });
62
+ return;
63
+ }
64
+ catch {
65
+ ctx.log('warn', 'Semgrep cache restored but binary not functional, reinstalling');
66
+ }
67
+ }
68
+ await ctx.exec('pip', ['install', '--quiet', `semgrep==${SEMGREP_VERSION}`], {
69
+ timeoutMs: 120_000,
70
+ });
71
+ await ctx.exec('semgrep', ['--version'], { timeoutMs: 10_000 });
72
+ await ctx.cacheSave('semgrep', ['/usr/local/bin/semgrep']);
73
+ },
74
+ async run(ctx, repoDir, _files, timeout) {
75
+ return ctx.exec('semgrep', ['--json', '--config', 'auto', '--quiet', repoDir], {
76
+ timeoutMs: timeout,
77
+ allowExitCodes: [1], // semgrep returns 1 when findings are present
78
+ });
79
+ },
80
+ parse: parseSemgrepOutput,
81
+ };
82
+ //# sourceMappingURL=semgrep.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semgrep.js","sourceRoot":"","sources":["../../../src/tools/plugins/semgrep.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * ShellCheck plugin — shell script linting (always-on).
3
+ *
4
+ * Lints shell scripts for common issues and portability problems.
5
+ * Only runs on *.sh and *.bash files; returns empty findings if none found.
6
+ *
7
+ * Pre-installed on GitHub Actions runners — install is a verification step.
8
+ * Uses ExecutionContext for DI instead of direct child_process.
9
+ */
10
+ import type { FindingSeverity, ReviewFinding } from '../../types.js';
11
+ import type { RawToolOutput, ToolDefinition } from '../types.js';
12
+ /**
13
+ * Map ShellCheck level to GHAGGA FindingSeverity.
14
+ * error→high, warning→medium, info→info, style→low
15
+ */
16
+ export declare function mapShellCheckSeverity(level: string): FindingSeverity;
17
+ /**
18
+ * Parse ShellCheck JSON output into ReviewFinding[].
19
+ * Exported for direct testing with fixture data.
20
+ */
21
+ export declare function parseShellCheckOutput(raw: RawToolOutput, repoDir: string): ReviewFinding[];
22
+ export declare const shellcheckPlugin: ToolDefinition;
23
+ //# sourceMappingURL=shellcheck.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shellcheck.d.ts","sourceRoot":"","sources":["../../../src/tools/plugins/shellcheck.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACrE,OAAO,KAAK,EAAoB,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAInF;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,eAAe,CAapE;AAYD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,GAAG,aAAa,EAAE,CAiB1F;AAED,eAAO,MAAM,gBAAgB,EAAE,cAiD9B,CAAC"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * ShellCheck plugin — shell script linting (always-on).
3
+ *
4
+ * Lints shell scripts for common issues and portability problems.
5
+ * Only runs on *.sh and *.bash files; returns empty findings if none found.
6
+ *
7
+ * Pre-installed on GitHub Actions runners — install is a verification step.
8
+ * Uses ExecutionContext for DI instead of direct child_process.
9
+ */
10
+ const SHELLCHECK_VERSION = '0.10.0';
11
+ /**
12
+ * Map ShellCheck level to GHAGGA FindingSeverity.
13
+ * error→high, warning→medium, info→info, style→low
14
+ */
15
+ export function mapShellCheckSeverity(level) {
16
+ switch (level.toLowerCase()) {
17
+ case 'error':
18
+ return 'high';
19
+ case 'warning':
20
+ return 'medium';
21
+ case 'info':
22
+ return 'info';
23
+ case 'style':
24
+ return 'low';
25
+ default:
26
+ return 'low';
27
+ }
28
+ }
29
+ /**
30
+ * Parse ShellCheck JSON output into ReviewFinding[].
31
+ * Exported for direct testing with fixture data.
32
+ */
33
+ export function parseShellCheckOutput(raw, repoDir) {
34
+ if (raw.timedOut)
35
+ return [];
36
+ try {
37
+ const findings = JSON.parse(raw.stdout);
38
+ return findings.map((f) => ({
39
+ severity: mapShellCheckSeverity(f.level),
40
+ category: 'quality',
41
+ file: f.file.replace(`${repoDir}/`, ''),
42
+ line: f.line,
43
+ message: `SC${f.code}: ${f.message}`,
44
+ source: 'shellcheck',
45
+ }));
46
+ }
47
+ catch {
48
+ return [];
49
+ }
50
+ }
51
+ export const shellcheckPlugin = {
52
+ name: 'shellcheck',
53
+ displayName: 'ShellCheck',
54
+ category: 'quality',
55
+ tier: 'always-on',
56
+ version: SHELLCHECK_VERSION,
57
+ outputFormat: 'json',
58
+ async install(ctx) {
59
+ // ShellCheck is typically pre-installed on GitHub Actions runners
60
+ try {
61
+ await ctx.exec('shellcheck', ['--version'], { timeoutMs: 10_000 });
62
+ return;
63
+ }
64
+ catch {
65
+ ctx.log('info', 'ShellCheck not found, installing...');
66
+ }
67
+ await ctx.exec('bash', [
68
+ '-c',
69
+ `curl -sL "https://github.com/koalaman/shellcheck/releases/download/v${SHELLCHECK_VERSION}/shellcheck-v${SHELLCHECK_VERSION}.linux.x86_64.tar.xz" | tar xJ --strip-components=1 -C /usr/local/bin shellcheck-v${SHELLCHECK_VERSION}/shellcheck`,
70
+ ], { timeoutMs: 120_000 });
71
+ await ctx.exec('shellcheck', ['--version'], { timeoutMs: 10_000 });
72
+ },
73
+ async run(ctx, _repoDir, files, timeout) {
74
+ // Filter to only shell script files
75
+ const shellFiles = files.filter((f) => /\.(sh|bash)$/.test(f));
76
+ if (shellFiles.length === 0) {
77
+ // No shell files — return empty output (will parse to empty findings)
78
+ return { stdout: '[]', stderr: '', exitCode: 0, timedOut: false };
79
+ }
80
+ return ctx.exec('shellcheck', ['--format=json', ...shellFiles], {
81
+ timeoutMs: timeout,
82
+ allowExitCodes: [1], // shellcheck returns 1 when findings are present
83
+ });
84
+ },
85
+ parse: parseShellCheckOutput,
86
+ };
87
+ //# sourceMappingURL=shellcheck.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shellcheck.js","sourceRoot":"","sources":["../../../src/tools/plugins/shellcheck.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Trivy plugin — SCA vulnerability + license scanning (always-on).
3
+ *
4
+ * Adapted from:
5
+ * - packages/core/src/tools/trivy.ts (parsing logic)
6
+ * - apps/action/src/tools/trivy.ts (install/run flow)
7
+ *
8
+ * Enhanced: adds --scanners license to existing vuln scanner.
9
+ * Uses ExecutionContext for DI instead of direct child_process.
10
+ */
11
+ import type { FindingSeverity, ReviewFinding } from '../../types.js';
12
+ import type { RawToolOutput, ToolDefinition } from '../types.js';
13
+ /**
14
+ * Map Trivy severity to GHAGGA FindingSeverity.
15
+ * CRITICAL -> critical, HIGH -> high, MEDIUM -> medium, LOW -> low, default -> info
16
+ */
17
+ export declare function mapTrivySeverity(trivySeverity: string): FindingSeverity;
18
+ /**
19
+ * Parse Trivy JSON output into ReviewFinding[].
20
+ * Handles both vulnerability and license findings.
21
+ * Exported for direct testing with fixture data.
22
+ */
23
+ export declare function parseTrivyOutput(raw: RawToolOutput, _repoDir: string): ReviewFinding[];
24
+ export declare const trivyPlugin: ToolDefinition;
25
+ //# sourceMappingURL=trivy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trivy.d.ts","sourceRoot":"","sources":["../../../src/tools/plugins/trivy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACrE,OAAO,KAAK,EAAoB,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAInF;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,aAAa,EAAE,MAAM,GAAG,eAAe,CAavE;AA0BD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,GAAG,aAAa,EAAE,CAuCtF;AAED,eAAO,MAAM,WAAW,EAAE,cAmDzB,CAAC"}
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Trivy plugin — SCA vulnerability + license scanning (always-on).
3
+ *
4
+ * Adapted from:
5
+ * - packages/core/src/tools/trivy.ts (parsing logic)
6
+ * - apps/action/src/tools/trivy.ts (install/run flow)
7
+ *
8
+ * Enhanced: adds --scanners license to existing vuln scanner.
9
+ * Uses ExecutionContext for DI instead of direct child_process.
10
+ */
11
+ const TRIVY_VERSION = '0.69.3';
12
+ /**
13
+ * Map Trivy severity to GHAGGA FindingSeverity.
14
+ * CRITICAL -> critical, HIGH -> high, MEDIUM -> medium, LOW -> low, default -> info
15
+ */
16
+ export function mapTrivySeverity(trivySeverity) {
17
+ switch (trivySeverity.toUpperCase()) {
18
+ case 'CRITICAL':
19
+ return 'critical';
20
+ case 'HIGH':
21
+ return 'high';
22
+ case 'MEDIUM':
23
+ return 'medium';
24
+ case 'LOW':
25
+ return 'low';
26
+ default:
27
+ return 'info';
28
+ }
29
+ }
30
+ /**
31
+ * Parse Trivy JSON output into ReviewFinding[].
32
+ * Handles both vulnerability and license findings.
33
+ * Exported for direct testing with fixture data.
34
+ */
35
+ export function parseTrivyOutput(raw, _repoDir) {
36
+ if (raw.timedOut)
37
+ return [];
38
+ try {
39
+ const result = JSON.parse(raw.stdout);
40
+ const findings = [];
41
+ for (const target of result.Results ?? []) {
42
+ // Parse vulnerability findings (existing behavior)
43
+ for (const vuln of target.Vulnerabilities ?? []) {
44
+ const fixInfo = vuln.FixedVersion
45
+ ? ` (fix: upgrade to ${vuln.FixedVersion})`
46
+ : ' (no fix available)';
47
+ findings.push({
48
+ severity: mapTrivySeverity(vuln.Severity),
49
+ category: 'dependency-vulnerability',
50
+ file: target.Target,
51
+ message: `${vuln.VulnerabilityID}: ${vuln.PkgName}@${vuln.InstalledVersion} - ${vuln.Title ?? vuln.Description ?? 'Known vulnerability'}${fixInfo}`,
52
+ source: 'trivy',
53
+ });
54
+ }
55
+ // Parse license findings (new enhancement)
56
+ for (const license of target.Licenses ?? []) {
57
+ findings.push({
58
+ severity: 'info',
59
+ category: 'license',
60
+ file: target.Target,
61
+ message: `${license.PkgName}: ${license.Name} (${license.Category})`,
62
+ source: 'trivy',
63
+ });
64
+ }
65
+ }
66
+ return findings;
67
+ }
68
+ catch {
69
+ return [];
70
+ }
71
+ }
72
+ export const trivyPlugin = {
73
+ name: 'trivy',
74
+ displayName: 'Trivy',
75
+ category: 'sca',
76
+ tier: 'always-on',
77
+ version: TRIVY_VERSION,
78
+ outputFormat: 'json',
79
+ cachePaths: ['/usr/local/bin/trivy'],
80
+ async install(ctx) {
81
+ const cached = await ctx.cacheRestore('trivy', ['/usr/local/bin/trivy']);
82
+ if (cached) {
83
+ try {
84
+ await ctx.exec('trivy', ['--version'], { timeoutMs: 10_000 });
85
+ return;
86
+ }
87
+ catch {
88
+ ctx.log('warn', 'Trivy cache restored but binary not functional, reinstalling');
89
+ }
90
+ }
91
+ // Install Trivy via official install script
92
+ await ctx.exec('bash', [
93
+ '-c',
94
+ `curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin v${TRIVY_VERSION}`,
95
+ ], { timeoutMs: 120_000 });
96
+ await ctx.exec('trivy', ['--version'], { timeoutMs: 10_000 });
97
+ await ctx.cacheSave('trivy', ['/usr/local/bin/trivy']);
98
+ },
99
+ async run(ctx, repoDir, _files, timeout) {
100
+ // Enhanced: adds 'license' scanner alongside 'vuln'
101
+ return ctx.exec('trivy', ['fs', '--format', 'json', '--scanners', 'vuln,license', '--quiet', repoDir], {
102
+ timeoutMs: timeout,
103
+ allowExitCodes: [1],
104
+ });
105
+ },
106
+ parse: parseTrivyOutput,
107
+ };
108
+ //# sourceMappingURL=trivy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trivy.js","sourceRoot":"","sources":["../../../src/tools/plugins/trivy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Tool Registry — central registration point for all static analysis tools.
3
+ *
4
+ * Plugins register themselves via `toolRegistry.register()`.
5
+ * The orchestrator discovers tools through `toolRegistry.getAll()`.
6
+ *
7
+ * Singleton pattern: one registry per process, populated at import time
8
+ * by `plugins/index.ts`.
9
+ */
10
+ import type { ToolDefinition, ToolTier } from './types.js';
11
+ export declare class ToolRegistry {
12
+ private tools;
13
+ /**
14
+ * Register a tool definition.
15
+ * Validates that auto-detect tools have a detect function.
16
+ * Throws on duplicate name registration.
17
+ */
18
+ register(tool: ToolDefinition): void;
19
+ /** Get all registered tools */
20
+ getAll(): ToolDefinition[];
21
+ /** Get tool by name, or undefined */
22
+ getByName(name: string): ToolDefinition | undefined;
23
+ /** Get tools by tier */
24
+ getByTier(tier: ToolTier): ToolDefinition[];
25
+ /** Get registered tool count */
26
+ get size(): number;
27
+ /** Validate all registrations (called once at startup) */
28
+ validateAll(): void;
29
+ /**
30
+ * Clear all registrations (useful for tests).
31
+ * @internal
32
+ */
33
+ clear(): void;
34
+ }
35
+ /** Singleton registry instance — populated by plugins/index.ts */
36
+ export declare const toolRegistry: ToolRegistry;
37
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/tools/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3D,qBAAa,YAAY;IACvB,OAAO,CAAC,KAAK,CAAqC;IAElD;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI;IAepC,+BAA+B;IAC/B,MAAM,IAAI,cAAc,EAAE;IAI1B,qCAAqC;IACrC,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;IAInD,wBAAwB;IACxB,SAAS,CAAC,IAAI,EAAE,QAAQ,GAAG,cAAc,EAAE;IAI3C,gCAAgC;IAChC,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,0DAA0D;IAC1D,WAAW,IAAI,IAAI;IAUnB;;;OAGG;IACH,KAAK,IAAI,IAAI;CAGd;AAED,kEAAkE;AAClE,eAAO,MAAM,YAAY,cAAqB,CAAC"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Tool Registry — central registration point for all static analysis tools.
3
+ *
4
+ * Plugins register themselves via `toolRegistry.register()`.
5
+ * The orchestrator discovers tools through `toolRegistry.getAll()`.
6
+ *
7
+ * Singleton pattern: one registry per process, populated at import time
8
+ * by `plugins/index.ts`.
9
+ */
10
+ export class ToolRegistry {
11
+ tools = new Map();
12
+ /**
13
+ * Register a tool definition.
14
+ * Validates that auto-detect tools have a detect function.
15
+ * Throws on duplicate name registration.
16
+ */
17
+ register(tool) {
18
+ if (this.tools.has(tool.name)) {
19
+ throw new Error(`Tool "${tool.name}" is already registered`);
20
+ }
21
+ if (tool.tier === 'auto-detect' && typeof tool.detect !== 'function') {
22
+ throw new Error(`Tool "${tool.name}" has tier "auto-detect" but no detect function. ` +
23
+ 'Auto-detect tools must provide a detect(files) function.');
24
+ }
25
+ this.tools.set(tool.name, tool);
26
+ }
27
+ /** Get all registered tools */
28
+ getAll() {
29
+ return Array.from(this.tools.values());
30
+ }
31
+ /** Get tool by name, or undefined */
32
+ getByName(name) {
33
+ return this.tools.get(name);
34
+ }
35
+ /** Get tools by tier */
36
+ getByTier(tier) {
37
+ return this.getAll().filter((t) => t.tier === tier);
38
+ }
39
+ /** Get registered tool count */
40
+ get size() {
41
+ return this.tools.size;
42
+ }
43
+ /** Validate all registrations (called once at startup) */
44
+ validateAll() {
45
+ for (const tool of this.tools.values()) {
46
+ if (tool.tier === 'auto-detect' && typeof tool.detect !== 'function') {
47
+ throw new Error(`Validation failed: tool "${tool.name}" is auto-detect but has no detect function`);
48
+ }
49
+ }
50
+ }
51
+ /**
52
+ * Clear all registrations (useful for tests).
53
+ * @internal
54
+ */
55
+ clear() {
56
+ this.tools.clear();
57
+ }
58
+ }
59
+ /** Singleton registry instance — populated by plugins/index.ts */
60
+ export const toolRegistry = new ToolRegistry();
61
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/tools/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,MAAM,OAAO,YAAY;IACf,KAAK,GAAG,IAAI,GAAG,EAA0B,CAAC;IAElD;;;;OAIG;IACH,QAAQ,CAAC,IAAoB;QAC3B,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CAAC,SAAS,IAAI,CAAC,IAAI,yBAAyB,CAAC,CAAC;QAC/D,CAAC;QAED,IAAI,IAAI,CAAC,IAAI,KAAK,aAAa,IAAI,OAAO,IAAI,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;YACrE,MAAM,IAAI,KAAK,CACb,SAAS,IAAI,CAAC,IAAI,mDAAmD;gBACnE,0DAA0D,CAC7D,CAAC;QACJ,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAClC,CAAC;IAED,+BAA+B;IAC/B,MAAM;QACJ,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;IACzC,CAAC;IAED,qCAAqC;IACrC,SAAS,CAAC,IAAY;QACpB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC9B,CAAC;IAED,wBAAwB;IACxB,SAAS,CAAC,IAAc;QACtB,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IACtD,CAAC;IAED,gCAAgC;IAChC,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IACzB,CAAC;IAED,0DAA0D;IAC1D,WAAW;QACT,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;YACvC,IAAI,IAAI,CAAC,IAAI,KAAK,aAAa,IAAI,OAAO,IAAI,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;gBACrE,MAAM,IAAI,KAAK,CACb,4BAA4B,IAAI,CAAC,IAAI,6CAA6C,CACnF,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,KAAK;QACH,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;CACF;AAED,kEAAkE;AAClE,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,YAAY,EAAE,CAAC"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Tool Activation Resolver — determines which tools should run.
3
+ *
4
+ * Resolution order (per spec):
5
+ * 1. Start with all always-on tools
6
+ * 2. Run detect(files) for each auto-detect tool; add matches
7
+ * 3. Add tools from enabledTools (force-enable override)
8
+ * 4. Remove tools from disabledTools (force-disable override)
9
+ * 5. Remove tools disabled by deprecated boolean flags (fallback only)
10
+ *
11
+ * disabledTools takes precedence over everything.
12
+ * New fields take precedence over deprecated boolean flags.
13
+ */
14
+ import type { ToolRegistry } from './registry.js';
15
+ import type { ToolDefinition } from './types.js';
16
+ export interface ToolActivationInput {
17
+ registry: ToolRegistry;
18
+ files: string[];
19
+ enabledTools?: string[];
20
+ disabledTools?: string[];
21
+ /** Deprecated boolean flags (backward compat) */
22
+ enableSemgrep?: boolean;
23
+ enableTrivy?: boolean;
24
+ enableCpd?: boolean;
25
+ }
26
+ export interface ActivatedTool {
27
+ definition: ToolDefinition;
28
+ reason: 'always-on' | 'auto-detect' | 'force-enabled';
29
+ }
30
+ /**
31
+ * Resolve which tools should run for this review.
32
+ *
33
+ * Returns activated tools in execution order: always-on first, then auto-detect,
34
+ * then force-enabled.
35
+ */
36
+ export declare function resolveActivatedTools(input: ToolActivationInput): ActivatedTool[];
37
+ //# sourceMappingURL=resolve.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../src/tools/resolve.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,YAAY,CAAC;IACvB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,iDAAiD;IACjD,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,cAAc,CAAC;IAC3B,MAAM,EAAE,WAAW,GAAG,aAAa,GAAG,eAAe,CAAC;CACvD;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,mBAAmB,GAAG,aAAa,EAAE,CAsDjF"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Tool Activation Resolver — determines which tools should run.
3
+ *
4
+ * Resolution order (per spec):
5
+ * 1. Start with all always-on tools
6
+ * 2. Run detect(files) for each auto-detect tool; add matches
7
+ * 3. Add tools from enabledTools (force-enable override)
8
+ * 4. Remove tools from disabledTools (force-disable override)
9
+ * 5. Remove tools disabled by deprecated boolean flags (fallback only)
10
+ *
11
+ * disabledTools takes precedence over everything.
12
+ * New fields take precedence over deprecated boolean flags.
13
+ */
14
+ /**
15
+ * Resolve which tools should run for this review.
16
+ *
17
+ * Returns activated tools in execution order: always-on first, then auto-detect,
18
+ * then force-enabled.
19
+ */
20
+ export function resolveActivatedTools(input) {
21
+ const { registry, files, enabledTools, disabledTools } = input;
22
+ const activated = new Map();
23
+ // Step 1: Start with all always-on tools
24
+ for (const tool of registry.getByTier('always-on')) {
25
+ activated.set(tool.name, { definition: tool, reason: 'always-on' });
26
+ }
27
+ // Step 2: Run detect(files) for each auto-detect tool
28
+ for (const tool of registry.getByTier('auto-detect')) {
29
+ if (tool.detect && tool.detect(files)) {
30
+ activated.set(tool.name, { definition: tool, reason: 'auto-detect' });
31
+ }
32
+ }
33
+ // Step 3: Add tools from enabledTools (force-enable)
34
+ if (enabledTools && enabledTools.length > 0) {
35
+ for (const name of enabledTools) {
36
+ if (!activated.has(name)) {
37
+ const tool = registry.getByName(name);
38
+ if (tool) {
39
+ activated.set(name, { definition: tool, reason: 'force-enabled' });
40
+ }
41
+ }
42
+ }
43
+ }
44
+ // Step 4: Remove tools from disabledTools (force-disable) — takes precedence over everything
45
+ if (disabledTools && disabledTools.length > 0) {
46
+ for (const name of disabledTools) {
47
+ activated.delete(name);
48
+ }
49
+ }
50
+ // Step 5: Apply deprecated boolean flags as fallback
51
+ // Only apply when the new disabledTools field does NOT already handle the tool
52
+ const hasNewDisabledField = disabledTools !== undefined && disabledTools.length > 0;
53
+ if (!hasNewDisabledField) {
54
+ const deprecatedFlags = [
55
+ { flag: input.enableSemgrep, tool: 'semgrep' },
56
+ { flag: input.enableTrivy, tool: 'trivy' },
57
+ { flag: input.enableCpd, tool: 'cpd' },
58
+ ];
59
+ for (const { flag, tool } of deprecatedFlags) {
60
+ if (flag === false) {
61
+ activated.delete(tool);
62
+ }
63
+ }
64
+ }
65
+ return Array.from(activated.values());
66
+ }
67
+ //# sourceMappingURL=resolve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../src/tools/resolve.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAqBH;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CAAC,KAA0B;IAC9D,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,GAAG,KAAK,CAAC;IAE/D,MAAM,SAAS,GAAG,IAAI,GAAG,EAAyB,CAAC;IAEnD,yCAAyC;IACzC,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,SAAS,CAAC,WAAW,CAAC,EAAE,CAAC;QACnD,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;IACtE,CAAC;IAED,sDAAsD;IACtD,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,SAAS,CAAC,aAAa,CAAC,EAAE,CAAC;QACrD,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;YACtC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC,CAAC;QACxE,CAAC;IACH,CAAC;IAED,qDAAqD;IACrD,IAAI,YAAY,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5C,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;YAChC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBACzB,MAAM,IAAI,GAAG,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;gBACtC,IAAI,IAAI,EAAE,CAAC;oBACT,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC,CAAC;gBACrE,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,6FAA6F;IAC7F,IAAI,aAAa,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9C,KAAK,MAAM,IAAI,IAAI,aAAa,EAAE,CAAC;YACjC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;IAED,qDAAqD;IACrD,+EAA+E;IAC/E,MAAM,mBAAmB,GAAG,aAAa,KAAK,SAAS,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC;IACpF,IAAI,CAAC,mBAAmB,EAAE,CAAC;QACzB,MAAM,eAAe,GAAuD;YAC1E,EAAE,IAAI,EAAE,KAAK,CAAC,aAAa,EAAE,IAAI,EAAE,SAAS,EAAE;YAC9C,EAAE,IAAI,EAAE,KAAK,CAAC,WAAW,EAAE,IAAI,EAAE,OAAO,EAAE;YAC1C,EAAE,IAAI,EAAE,KAAK,CAAC,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE;SACvC,CAAC;QAEF,KAAK,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,eAAe,EAAE,CAAC;YAC7C,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;gBACnB,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YACzB,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC;AACxC,CAAC"}
@@ -4,19 +4,33 @@
4
4
  *
5
5
  * These tools are run one at a time because running them in parallel
6
6
  * (Python + JVM + Go) can exceed container memory limits (2GB on Cloud Run).
7
+ *
8
+ * Feature flag `GHAGGA_TOOL_REGISTRY`:
9
+ * - When true: uses the new registry-driven orchestrator (Phase 2+)
10
+ * - When false/unset: uses the existing hardcoded 3-tool path
11
+ */
12
+ import type { ReviewSettings, StaticAnalysisResult } from '../types.js';
13
+ /**
14
+ * Check if the tool registry feature flag is enabled.
7
15
  */
8
- import type { StaticAnalysisResult, ReviewSettings } from '../types.js';
16
+ export declare function isToolRegistryEnabled(): boolean;
9
17
  /**
10
18
  * Run all enabled static analysis tools sequentially.
11
19
  *
20
+ * When GHAGGA_TOOL_REGISTRY=true, uses the registry-driven orchestrator.
21
+ * Otherwise, falls back to the hardcoded 3-tool path.
22
+ *
12
23
  * @param files - Map of file paths to file contents (for Semgrep)
13
24
  * @param scanPath - Directory path on disk (for Trivy and CPD)
14
25
  * @param settings - Which tools are enabled
15
26
  */
16
- export declare function runStaticAnalysis(files: Map<string, string>, scanPath: string, settings: Pick<ReviewSettings, 'enableSemgrep' | 'enableTrivy' | 'enableCpd' | 'customRules'>): Promise<StaticAnalysisResult>;
27
+ export declare function runStaticAnalysis(files: Map<string, string>, scanPath: string, settings: Pick<ReviewSettings, 'enableSemgrep' | 'enableTrivy' | 'enableCpd' | 'customRules' | 'enabledTools' | 'disabledTools'>): Promise<StaticAnalysisResult>;
17
28
  /**
18
29
  * Format static analysis findings into a prompt context block.
19
30
  * This is injected into LLM prompts so agents don't repeat findings.
31
+ *
32
+ * Iterates all tool results dynamically (not hardcoded to semgrep/trivy/cpd).
33
+ * Applies a finding cap of 200 with severity-priority sorting.
20
34
  */
21
35
  export declare function formatStaticAnalysisContext(result: StaticAnalysisResult): string;
22
36
  //# sourceMappingURL=runner.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/tools/runner.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,KAAK,EAAE,oBAAoB,EAAE,cAAc,EAAc,MAAM,aAAa,CAAC;AAyBpF;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAC1B,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,IAAI,CAAC,cAAc,EAAE,eAAe,GAAG,aAAa,GAAG,WAAW,GAAG,aAAa,CAAC,GAC5F,OAAO,CAAC,oBAAoB,CAAC,CAqB/B;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,oBAAoB,GAAG,MAAM,CAqBhF"}
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/tools/runner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAiB,cAAc,EAAE,oBAAoB,EAAc,MAAM,aAAa,CAAC;AAoBnG;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,OAAO,CAE/C;AAkBD;;;;;;;;;GASG;AACH,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAC1B,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,IAAI,CACZ,cAAc,EACd,eAAe,GAAG,aAAa,GAAG,WAAW,GAAG,aAAa,GAAG,cAAc,GAAG,eAAe,CACjG,GACA,OAAO,CAAC,oBAAoB,CAAC,CA6B/B;AA8CD;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,oBAAoB,GAAG,MAAM,CAqChF"}