guardrail-core 1.0.0 → 2.0.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 (74) hide show
  1. package/dist/__tests__/autopilot-enterprise.test.d.ts +7 -0
  2. package/dist/__tests__/autopilot-enterprise.test.d.ts.map +1 -0
  3. package/dist/__tests__/autopilot-enterprise.test.js +334 -0
  4. package/dist/autopilot/autopilot-runner.d.ts +9 -0
  5. package/dist/autopilot/autopilot-runner.d.ts.map +1 -1
  6. package/dist/autopilot/autopilot-runner.js +182 -1
  7. package/dist/autopilot/types.d.ts +18 -2
  8. package/dist/autopilot/types.d.ts.map +1 -1
  9. package/dist/index.d.ts +1 -0
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +1 -0
  12. package/dist/smells/index.d.ts +59 -0
  13. package/dist/smells/index.d.ts.map +1 -0
  14. package/dist/smells/index.js +251 -0
  15. package/package.json +19 -2
  16. package/src/__tests__/autopilot.test.ts +0 -196
  17. package/src/__tests__/tier-config.test.ts +0 -289
  18. package/src/__tests__/utils/hash-inline.test.ts +0 -76
  19. package/src/__tests__/utils/hash.test.ts +0 -119
  20. package/src/__tests__/utils/simple.test.ts +0 -10
  21. package/src/__tests__/utils/utils-simple.test.ts +0 -5
  22. package/src/__tests__/utils/utils.test.ts +0 -203
  23. package/src/autopilot/autopilot-runner.ts +0 -503
  24. package/src/autopilot/index.ts +0 -6
  25. package/src/autopilot/types.ts +0 -119
  26. package/src/cache/index.ts +0 -7
  27. package/src/cache/redis-cache.d.ts +0 -155
  28. package/src/cache/redis-cache.d.ts.map +0 -1
  29. package/src/cache/redis-cache.ts +0 -517
  30. package/src/ci/github-actions.ts +0 -335
  31. package/src/ci/index.ts +0 -12
  32. package/src/ci/pre-commit.ts +0 -338
  33. package/src/db/usage-schema.prisma +0 -114
  34. package/src/entitlements.ts +0 -570
  35. package/src/env.d.ts +0 -68
  36. package/src/env.d.ts.map +0 -1
  37. package/src/env.ts +0 -247
  38. package/src/fix-packs/__tests__/generate-fix-packs.test.ts +0 -317
  39. package/src/fix-packs/generate-fix-packs.ts +0 -577
  40. package/src/fix-packs/index.ts +0 -8
  41. package/src/fix-packs/types.ts +0 -206
  42. package/src/index.d.ts +0 -7
  43. package/src/index.d.ts.map +0 -1
  44. package/src/index.ts +0 -12
  45. package/src/metrics/prometheus.d.ts +0 -104
  46. package/src/metrics/prometheus.d.ts.map +0 -1
  47. package/src/metrics/prometheus.ts +0 -446
  48. package/src/quota-ledger.ts +0 -548
  49. package/src/rbac/__tests__/permissions.test.ts +0 -446
  50. package/src/rbac/index.ts +0 -46
  51. package/src/rbac/permissions.ts +0 -301
  52. package/src/rbac/types.ts +0 -298
  53. package/src/tier-config.json +0 -157
  54. package/src/tier-config.ts +0 -815
  55. package/src/types.d.ts +0 -365
  56. package/src/types.d.ts.map +0 -1
  57. package/src/types.ts +0 -441
  58. package/src/utils.d.ts +0 -36
  59. package/src/utils.d.ts.map +0 -1
  60. package/src/utils.ts +0 -140
  61. package/src/verified-autofix/__tests__/format-validator.test.ts +0 -335
  62. package/src/verified-autofix/__tests__/pipeline.test.ts +0 -419
  63. package/src/verified-autofix/__tests__/repo-fingerprint.test.ts +0 -241
  64. package/src/verified-autofix/__tests__/workspace.test.ts +0 -373
  65. package/src/verified-autofix/format-validator.ts +0 -517
  66. package/src/verified-autofix/index.ts +0 -63
  67. package/src/verified-autofix/pipeline.ts +0 -403
  68. package/src/verified-autofix/repo-fingerprint.ts +0 -459
  69. package/src/verified-autofix/workspace.ts +0 -531
  70. package/src/verified-autofix.ts +0 -1187
  71. package/src/visualization/dependency-graph.d.ts +0 -85
  72. package/src/visualization/dependency-graph.d.ts.map +0 -1
  73. package/src/visualization/dependency-graph.ts +0 -495
  74. package/src/visualization/index.ts +0 -5
@@ -1,577 +0,0 @@
1
- /**
2
- * Fix Packs Generator
3
- *
4
- * Generates deterministic Fix Packs from findings and repo fingerprint.
5
- * Groups findings by category, file proximity, and risk level.
6
- */
7
-
8
- import * as crypto from 'crypto';
9
- import {
10
- Finding,
11
- FindingCategory,
12
- FixPack,
13
- FixStrategy,
14
- RepoFingerprint,
15
- GenerateFixPacksOptions,
16
- GenerateFixPacksResult,
17
- SeverityLevel,
18
- SEVERITY_ORDER,
19
- EstimatedImpact,
20
- generatePackId,
21
- getHighestSeverity,
22
- compareSeverity,
23
- } from './types';
24
-
25
- // ============================================================================
26
- // CONSTANTS
27
- // ============================================================================
28
-
29
- const DEFAULT_MAX_PACK_SIZE = 10;
30
- const DEFAULT_MIN_PACK_SIZE = 1;
31
- const FILE_PROXIMITY_THRESHOLD = 2;
32
-
33
- const CATEGORY_PRIORITY: Record<FindingCategory, number> = {
34
- secrets: 0,
35
- auth: 1,
36
- security: 2,
37
- routes: 3,
38
- mocks: 4,
39
- placeholders: 5,
40
- deps: 6,
41
- types: 7,
42
- tests: 8,
43
- performance: 9,
44
- };
45
-
46
- const CATEGORY_STRATEGY: Record<FindingCategory, FixStrategy> = {
47
- secrets: 'auto',
48
- auth: 'guided',
49
- security: 'guided',
50
- routes: 'auto',
51
- mocks: 'auto',
52
- placeholders: 'auto',
53
- deps: 'guided',
54
- types: 'ai-assisted',
55
- tests: 'ai-assisted',
56
- performance: 'manual',
57
- };
58
-
59
- const CATEGORY_REQUIRES_REVIEW: Record<FindingCategory, boolean> = {
60
- secrets: false,
61
- auth: true,
62
- security: true,
63
- routes: false,
64
- mocks: false,
65
- placeholders: false,
66
- deps: true,
67
- types: false,
68
- tests: true,
69
- performance: true,
70
- };
71
-
72
- // ============================================================================
73
- // MAIN GENERATOR
74
- // ============================================================================
75
-
76
- export function generateFixPacks(options: GenerateFixPacksOptions): GenerateFixPacksResult {
77
- const {
78
- findings,
79
- repoFingerprint,
80
- groupByCategory = true,
81
- groupByFileProximity = true,
82
- maxPackSize = DEFAULT_MAX_PACK_SIZE,
83
- minPackSize = DEFAULT_MIN_PACK_SIZE,
84
- } = options;
85
-
86
- if (findings.length === 0) {
87
- return {
88
- packs: [],
89
- ungrouped: [],
90
- stats: {
91
- totalFindings: 0,
92
- totalPacks: 0,
93
- byCategory: {} as Record<FindingCategory, number>,
94
- bySeverity: {} as Record<SeverityLevel, number>,
95
- },
96
- };
97
- }
98
-
99
- const sortedFindings = sortFindings(findings);
100
- let grouped: Map<string, Finding[]>;
101
-
102
- if (groupByCategory) {
103
- grouped = groupByCategories(sortedFindings);
104
- } else {
105
- grouped = new Map([['all', sortedFindings]]);
106
- }
107
-
108
- if (groupByFileProximity) {
109
- grouped = applyFileProximityGrouping(grouped, maxPackSize);
110
- }
111
-
112
- const packs: FixPack[] = [];
113
- const ungrouped: Finding[] = [];
114
- let packIndex = 0;
115
-
116
- const sortedGroups = Array.from(grouped.entries()).sort((a, b) => {
117
- const catA = a[1][0]?.category || 'performance';
118
- const catB = b[1][0]?.category || 'performance';
119
- return CATEGORY_PRIORITY[catA] - CATEGORY_PRIORITY[catB];
120
- });
121
-
122
- for (const [, groupFindings] of sortedGroups) {
123
- if (groupFindings.length < minPackSize) {
124
- ungrouped.push(...groupFindings);
125
- continue;
126
- }
127
-
128
- const chunks = chunkFindings(groupFindings, maxPackSize);
129
-
130
- for (const chunk of chunks) {
131
- const pack = createFixPack(chunk, repoFingerprint, packIndex++);
132
- packs.push(pack);
133
- }
134
- }
135
-
136
- const stats = calculateStats(findings, packs);
137
-
138
- return {
139
- packs: sortPacksBySeverityAndPriority(packs),
140
- ungrouped,
141
- stats,
142
- };
143
- }
144
-
145
- // ============================================================================
146
- // SORTING
147
- // ============================================================================
148
-
149
- function sortFindings(findings: Finding[]): Finding[] {
150
- return [...findings].sort((a, b) => {
151
- const severityDiff = compareSeverity(a.severity, b.severity);
152
- if (severityDiff !== 0) return severityDiff;
153
-
154
- const categoryDiff = CATEGORY_PRIORITY[a.category] - CATEGORY_PRIORITY[b.category];
155
- if (categoryDiff !== 0) return categoryDiff;
156
-
157
- const fileDiff = a.file.localeCompare(b.file);
158
- if (fileDiff !== 0) return fileDiff;
159
-
160
- return (a.line || 0) - (b.line || 0);
161
- });
162
- }
163
-
164
- function sortPacksBySeverityAndPriority(packs: FixPack[]): FixPack[] {
165
- return [...packs].sort((a, b) => {
166
- const severityDiff = compareSeverity(a.severity, b.severity);
167
- if (severityDiff !== 0) return severityDiff;
168
-
169
- return CATEGORY_PRIORITY[a.category] - CATEGORY_PRIORITY[b.category];
170
- });
171
- }
172
-
173
- // ============================================================================
174
- // GROUPING
175
- // ============================================================================
176
-
177
- function groupByCategories(findings: Finding[]): Map<string, Finding[]> {
178
- const groups = new Map<string, Finding[]>();
179
-
180
- for (const finding of findings) {
181
- const key = finding.category;
182
- if (!groups.has(key)) {
183
- groups.set(key, []);
184
- }
185
- groups.get(key)!.push(finding);
186
- }
187
-
188
- return groups;
189
- }
190
-
191
- function applyFileProximityGrouping(
192
- groups: Map<string, Finding[]>,
193
- _maxPackSize: number
194
- ): Map<string, Finding[]> {
195
- const result = new Map<string, Finding[]>();
196
-
197
- for (const [category, findings] of groups) {
198
- const fileGroups = new Map<string, Finding[]>();
199
-
200
- for (const finding of findings) {
201
- const dirPath = getDirectoryPath(finding.file, FILE_PROXIMITY_THRESHOLD);
202
- if (!fileGroups.has(dirPath)) {
203
- fileGroups.set(dirPath, []);
204
- }
205
- fileGroups.get(dirPath)!.push(finding);
206
- }
207
-
208
- let subIndex = 0;
209
- for (const [dirPath, dirFindings] of fileGroups) {
210
- const key = `${category}:${dirPath}:${subIndex++}`;
211
- result.set(key, dirFindings);
212
- }
213
- }
214
-
215
- return result;
216
- }
217
-
218
- function getDirectoryPath(filePath: string, depth: number): string {
219
- const parts = filePath.split(/[/\\]/);
220
- if (parts.length <= depth) {
221
- return parts.slice(0, -1).join('/') || '/';
222
- }
223
- return parts.slice(0, depth).join('/');
224
- }
225
-
226
- function chunkFindings(findings: Finding[], maxSize: number): Finding[][] {
227
- const chunks: Finding[][] = [];
228
- for (let i = 0; i < findings.length; i += maxSize) {
229
- chunks.push(findings.slice(i, i + maxSize));
230
- }
231
- return chunks;
232
- }
233
-
234
- // ============================================================================
235
- // PACK CREATION
236
- // ============================================================================
237
-
238
- function createFixPack(
239
- findings: Finding[],
240
- repoFingerprint: RepoFingerprint,
241
- index: number
242
- ): FixPack {
243
- const category = findings[0]?.category || 'security';
244
- const severities = findings.map(f => f.severity);
245
- const severity = getHighestSeverity(severities);
246
- const files = [...new Set(findings.map(f => f.file))];
247
-
248
- const packHash = generateDeterministicHash(findings, repoFingerprint);
249
- const id = generatePackId(category, index, packHash);
250
-
251
- const estimatedImpact = estimateImpact(findings, files);
252
- const strategy = CATEGORY_STRATEGY[category];
253
- const requiresHumanReview = CATEGORY_REQUIRES_REVIEW[category] ||
254
- severity === 'critical' ||
255
- estimatedImpact.riskLevel === 'high';
256
-
257
- const title = generatePackTitle(category, findings.length, severity);
258
-
259
- return {
260
- id,
261
- title,
262
- severity,
263
- findings,
264
- files,
265
- strategy,
266
- estimatedImpact,
267
- requiresHumanReview,
268
- category,
269
- createdAt: new Date().toISOString(),
270
- metadata: {
271
- repoFingerprint: repoFingerprint.hash,
272
- generatedBy: 'guardrail-fix-packs',
273
- version: '1.0.0',
274
- },
275
- };
276
- }
277
-
278
- function generatePackTitle(
279
- category: FindingCategory,
280
- findingCount: number,
281
- severity: SeverityLevel
282
- ): string {
283
- const categoryNames: Record<FindingCategory, string> = {
284
- secrets: 'Secret Exposure',
285
- auth: 'Authentication Issues',
286
- security: 'Security Vulnerabilities',
287
- routes: 'Route Integrity',
288
- mocks: 'Mock/Demo Code',
289
- placeholders: 'Placeholder Content',
290
- deps: 'Dependency Issues',
291
- types: 'Type Errors',
292
- tests: 'Test Failures',
293
- performance: 'Performance Issues',
294
- };
295
-
296
- const severityPrefix = severity === 'critical' || severity === 'high'
297
- ? `[${severity.toUpperCase()}] `
298
- : '';
299
-
300
- return `${severityPrefix}${categoryNames[category]} (${findingCount} ${findingCount === 1 ? 'issue' : 'issues'})`;
301
- }
302
-
303
- function generateDeterministicHash(findings: Finding[], repoFingerprint: RepoFingerprint): string {
304
- const data = findings.map(f => `${f.id}:${f.file}:${f.line || 0}`).sort().join('|');
305
- const combined = `${repoFingerprint.hash}:${data}`;
306
- return crypto.createHash('sha256').update(combined).digest('hex');
307
- }
308
-
309
- function estimateImpact(findings: Finding[], files: string[]): EstimatedImpact {
310
- const filesAffected = files.length;
311
- const linesChanged = findings.reduce((sum, f) => {
312
- const lineSpan = (f.endLine || f.line || 1) - (f.line || 1) + 1;
313
- return sum + Math.max(lineSpan, 1);
314
- }, 0);
315
-
316
- let riskLevel: 'low' | 'medium' | 'high' = 'low';
317
- const hasCritical = findings.some(f => f.severity === 'critical');
318
- const hasHigh = findings.some(f => f.severity === 'high');
319
-
320
- if (hasCritical || filesAffected > 10) {
321
- riskLevel = 'high';
322
- } else if (hasHigh || filesAffected > 5) {
323
- riskLevel = 'medium';
324
- }
325
-
326
- const confidence = calculateConfidence(findings);
327
- const timeEstimateMinutes = Math.ceil(findings.length * 2 + filesAffected * 3);
328
-
329
- return {
330
- filesAffected,
331
- linesChanged,
332
- riskLevel,
333
- confidence,
334
- timeEstimateMinutes,
335
- };
336
- }
337
-
338
- function calculateConfidence(findings: Finding[]): number {
339
- const hasAutoFix = findings.filter(f => f.suggestion).length;
340
- const autoFixRatio = findings.length > 0 ? hasAutoFix / findings.length : 0;
341
-
342
- const avgSeverityScore = findings.reduce((sum, f) => {
343
- return sum + (4 - SEVERITY_ORDER[f.severity]);
344
- }, 0) / Math.max(findings.length, 1);
345
-
346
- return Math.min(100, Math.round((autoFixRatio * 50) + (avgSeverityScore * 10) + 20));
347
- }
348
-
349
- // ============================================================================
350
- // STATS
351
- // ============================================================================
352
-
353
- function calculateStats(
354
- findings: Finding[],
355
- packs: FixPack[]
356
- ): GenerateFixPacksResult['stats'] {
357
- const byCategory = {} as Record<FindingCategory, number>;
358
- const bySeverity = {} as Record<SeverityLevel, number>;
359
-
360
- for (const finding of findings) {
361
- byCategory[finding.category] = (byCategory[finding.category] || 0) + 1;
362
- bySeverity[finding.severity] = (bySeverity[finding.severity] || 0) + 1;
363
- }
364
-
365
- return {
366
- totalFindings: findings.length,
367
- totalPacks: packs.length,
368
- byCategory,
369
- bySeverity,
370
- };
371
- }
372
-
373
- // ============================================================================
374
- // REPO FINGERPRINT GENERATOR
375
- // ============================================================================
376
-
377
- export function generateRepoFingerprint(
378
- projectPath: string,
379
- options?: {
380
- name?: string;
381
- framework?: string;
382
- language?: string;
383
- }
384
- ): RepoFingerprint {
385
- const fs = require('fs');
386
- const path = require('path');
387
-
388
- const name = options?.name || path.basename(projectPath);
389
- let hasTypeScript = false;
390
- let hasTests = false;
391
- let packageManager: 'npm' | 'yarn' | 'pnpm' | undefined;
392
- let gitRemote: string | undefined;
393
-
394
- try {
395
- hasTypeScript = fs.existsSync(path.join(projectPath, 'tsconfig.json'));
396
- } catch { /* ignore */ }
397
-
398
- try {
399
- const testDirs = ['tests', 'test', '__tests__', 'spec'];
400
- hasTests = testDirs.some(dir => fs.existsSync(path.join(projectPath, dir)));
401
- } catch { /* ignore */ }
402
-
403
- try {
404
- if (fs.existsSync(path.join(projectPath, 'pnpm-lock.yaml'))) {
405
- packageManager = 'pnpm';
406
- } else if (fs.existsSync(path.join(projectPath, 'yarn.lock'))) {
407
- packageManager = 'yarn';
408
- } else if (fs.existsSync(path.join(projectPath, 'package-lock.json'))) {
409
- packageManager = 'npm';
410
- }
411
- } catch { /* ignore */ }
412
-
413
- try {
414
- const { execSync } = require('child_process');
415
- gitRemote = execSync('git remote get-url origin', {
416
- cwd: projectPath,
417
- encoding: 'utf8',
418
- stdio: ['pipe', 'pipe', 'pipe'],
419
- }).trim();
420
- } catch { /* ignore */ }
421
-
422
- const fingerprintData = `${name}:${hasTypeScript}:${hasTests}:${packageManager || ''}:${gitRemote || ''}`;
423
- const hash = crypto.createHash('sha256').update(fingerprintData).digest('hex').slice(0, 12);
424
-
425
- return {
426
- id: `repo-${hash}`,
427
- name,
428
- framework: options?.framework,
429
- language: options?.language || (hasTypeScript ? 'typescript' : 'javascript'),
430
- hasTypeScript,
431
- hasTests,
432
- packageManager,
433
- gitRemote,
434
- hash,
435
- };
436
- }
437
-
438
- // ============================================================================
439
- // FINDING PARSERS
440
- // ============================================================================
441
-
442
- export function parseFindingsFromScanOutput(scanOutput: string): Finding[] {
443
- const findings: Finding[] = [];
444
-
445
- try {
446
- const json = JSON.parse(scanOutput);
447
- if (Array.isArray(json.findings)) {
448
- return json.findings.map((f: any, i: number) => normalizeFinding(f, i));
449
- }
450
- if (Array.isArray(json.issues)) {
451
- return json.issues.map((f: any, i: number) => normalizeFinding(f, i));
452
- }
453
- if (Array.isArray(json)) {
454
- return json.map((f: any, i: number) => normalizeFinding(f, i));
455
- }
456
- } catch {
457
- return parseTextFindings(scanOutput);
458
- }
459
-
460
- return findings;
461
- }
462
-
463
- function normalizeFinding(raw: any, index: number): Finding {
464
- return {
465
- id: raw.id || raw.ruleId || `finding-${index}`,
466
- category: normalizeCategory(raw.category || raw.type || 'security'),
467
- severity: normalizeSeverity(raw.severity || raw.level || 'medium'),
468
- title: raw.title || raw.message || raw.description || 'Unknown issue',
469
- description: raw.description || raw.message || '',
470
- file: raw.file || raw.filePath || raw.path || 'unknown',
471
- line: raw.line || raw.startLine || raw.location?.line,
472
- column: raw.column || raw.startColumn || raw.location?.column,
473
- endLine: raw.endLine || raw.location?.endLine,
474
- endColumn: raw.endColumn || raw.location?.endColumn,
475
- code: raw.code || raw.source,
476
- suggestion: raw.suggestion || raw.fix || raw.recommendation,
477
- rule: raw.rule || raw.ruleId,
478
- metadata: raw.metadata || {},
479
- };
480
- }
481
-
482
- function normalizeCategory(category: string): FindingCategory {
483
- const categoryMap: Record<string, FindingCategory> = {
484
- 'secret': 'secrets',
485
- 'secrets': 'secrets',
486
- 'credential': 'secrets',
487
- 'api-key': 'secrets',
488
- 'route': 'routes',
489
- 'routes': 'routes',
490
- 'dead-link': 'routes',
491
- 'orphan': 'routes',
492
- 'mock': 'mocks',
493
- 'mocks': 'mocks',
494
- 'demo': 'mocks',
495
- 'fake': 'mocks',
496
- 'auth': 'auth',
497
- 'authentication': 'auth',
498
- 'authorization': 'auth',
499
- 'placeholder': 'placeholders',
500
- 'placeholders': 'placeholders',
501
- 'lorem': 'placeholders',
502
- 'todo': 'placeholders',
503
- 'dep': 'deps',
504
- 'deps': 'deps',
505
- 'dependency': 'deps',
506
- 'dependencies': 'deps',
507
- 'vulnerability': 'deps',
508
- 'type': 'types',
509
- 'types': 'types',
510
- 'typescript': 'types',
511
- 'test': 'tests',
512
- 'tests': 'tests',
513
- 'spec': 'tests',
514
- 'security': 'security',
515
- 'xss': 'security',
516
- 'injection': 'security',
517
- 'performance': 'performance',
518
- 'perf': 'performance',
519
- };
520
-
521
- const normalized = category.toLowerCase();
522
- return categoryMap[normalized] || 'security';
523
- }
524
-
525
- function normalizeSeverity(severity: string): SeverityLevel {
526
- const severityMap: Record<string, SeverityLevel> = {
527
- 'critical': 'critical',
528
- 'blocker': 'critical',
529
- 'high': 'high',
530
- 'error': 'high',
531
- 'major': 'high',
532
- 'medium': 'medium',
533
- 'warning': 'medium',
534
- 'moderate': 'medium',
535
- 'low': 'low',
536
- 'minor': 'low',
537
- 'info': 'info',
538
- 'informational': 'info',
539
- 'note': 'info',
540
- };
541
-
542
- const normalized = severity.toLowerCase();
543
- return severityMap[normalized] || 'medium';
544
- }
545
-
546
- function parseTextFindings(text: string): Finding[] {
547
- const findings: Finding[] = [];
548
- const lines = text.split('\n');
549
-
550
- const patterns = [
551
- /^(.+):(\d+):(\d+):\s*(error|warning|info):\s*(.+)$/i,
552
- /^(.+)\((\d+),(\d+)\):\s*(error|warning|info)\s+\w+:\s*(.+)$/i,
553
- /^\s*(error|warning|info)\s+(.+)\s+in\s+(.+):(\d+)/i,
554
- ];
555
-
556
- let index = 0;
557
- for (const line of lines) {
558
- for (const pattern of patterns) {
559
- const match = line.match(pattern);
560
- if (match) {
561
- findings.push({
562
- id: `text-finding-${index++}`,
563
- category: 'security',
564
- severity: normalizeSeverity(match[4] || 'medium'),
565
- title: match[5] || match[2] || 'Unknown issue',
566
- description: line,
567
- file: match[1] || match[3] || 'unknown',
568
- line: parseInt(match[2] || match[4] || '0', 10) || undefined,
569
- column: parseInt(match[3] || '0', 10) || undefined,
570
- });
571
- break;
572
- }
573
- }
574
- }
575
-
576
- return findings;
577
- }
@@ -1,8 +0,0 @@
1
- /**
2
- * Fix Packs Module
3
- *
4
- * First-class objects that group findings into actionable batches.
5
- */
6
-
7
- export * from './types';
8
- export * from './generate-fix-packs';