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,403 +0,0 @@
1
- /**
2
- * Verified AutoFix Pipeline - Orchestration Layer
3
- *
4
- * Pipeline order:
5
- * 1. format → validate JSON shape + strip markdown
6
- * 2. diff/path safety → validate unified diff + paths within project
7
- * 3. command safety → warn on risky commands
8
- * 4. stub detection → block TODO/placeholder in production
9
- * 5. apply diff → git apply --check then git apply
10
- * 6. typecheck → tsc --noEmit
11
- * 7. build (ship) → npm run build
12
- * 8. tests → npm test
13
- */
14
-
15
- import * as fs from 'fs';
16
- import {
17
- validateAgentOutput,
18
- type FullValidationResult,
19
- type GuardrailV1Output,
20
- } from './format-validator';
21
- import { TempWorkspace, type VerifyResult } from './workspace';
22
- import { fingerprintRepo, type RepoFingerprint } from './repo-fingerprint';
23
- import { trackUsage, enforceFeature } from '../entitlements';
24
-
25
- // ============================================================================
26
- // TYPES
27
- // ============================================================================
28
-
29
- export interface PipelineOptions {
30
- projectPath: string;
31
- agentOutputFile?: string;
32
- agentOutputRaw?: string;
33
- dryRun?: boolean;
34
- skipTests?: boolean;
35
- verbose?: boolean;
36
- timeout?: number;
37
- skipEntitlements?: boolean;
38
- strictMarkdown?: boolean;
39
- onProgress?: (stage: PipelineStage, message: string, data?: unknown) => void;
40
- }
41
-
42
- export type PipelineStage =
43
- | 'init'
44
- | 'validate'
45
- | 'fingerprint'
46
- | 'workspace'
47
- | 'apply'
48
- | 'typecheck'
49
- | 'build'
50
- | 'test'
51
- | 'commit'
52
- | 'done'
53
- | 'error';
54
-
55
- export interface PipelineResult {
56
- success: boolean;
57
- stage: PipelineStage;
58
- duration: number;
59
- validation?: FullValidationResult;
60
- fingerprint?: RepoFingerprint;
61
- verification?: VerifyResult;
62
- filesModified: string[];
63
- errors: string[];
64
- warnings: string[];
65
- failureContext: string[];
66
- output?: GuardrailV1Output;
67
- }
68
-
69
- // ============================================================================
70
- // PIPELINE CLASS
71
- // ============================================================================
72
-
73
- export class VerifiedAutofixPipeline {
74
- private workspace: TempWorkspace;
75
-
76
- constructor() {
77
- this.workspace = new TempWorkspace();
78
- }
79
-
80
- /**
81
- * Run the full verification pipeline
82
- */
83
- async run(options: PipelineOptions): Promise<PipelineResult> {
84
- const startTime = Date.now();
85
- const result: PipelineResult = {
86
- success: false,
87
- stage: 'init',
88
- duration: 0,
89
- filesModified: [],
90
- errors: [],
91
- warnings: [],
92
- failureContext: [],
93
- };
94
-
95
- let workspaceId: string | null = null;
96
-
97
- try {
98
- // Enforce feature entitlement (Pro+ required) unless skipped
99
- if (!options.skipEntitlements && process.env['GUARDRAIL_SKIP_ENTITLEMENTS'] !== '1') {
100
- await enforceFeature('fix:auto');
101
- }
102
-
103
- options.onProgress?.('init', 'Starting verified autofix pipeline');
104
-
105
- // Step 1: Read agent output
106
- result.stage = 'validate';
107
- options.onProgress?.('validate', 'Reading agent output');
108
-
109
- let rawOutput: string;
110
- if (options.agentOutputFile) {
111
- if (!fs.existsSync(options.agentOutputFile)) {
112
- throw new Error(`Agent output file not found: ${options.agentOutputFile}`);
113
- }
114
- rawOutput = await fs.promises.readFile(options.agentOutputFile, 'utf8');
115
- } else if (options.agentOutputRaw) {
116
- rawOutput = options.agentOutputRaw;
117
- } else {
118
- throw new Error('Either agentOutputFile or agentOutputRaw must be provided');
119
- }
120
-
121
- // Step 2: Validate format
122
- options.onProgress?.('validate', 'Validating output format');
123
- const validation = validateAgentOutput(rawOutput, options.projectPath, {
124
- strictMarkdown: options.strictMarkdown,
125
- });
126
- result.validation = validation;
127
-
128
- if (!validation.valid || !validation.output) {
129
- result.errors.push(...validation.errors);
130
- result.warnings.push(...validation.warnings);
131
- throw new Error(`Validation failed: ${validation.errors.join('; ')}`);
132
- }
133
-
134
- result.output = validation.output;
135
- result.warnings.push(...validation.warnings);
136
- result.filesModified = validation.diffValidation?.filesAffected || [];
137
-
138
- options.onProgress?.('validate', `Validated ${result.filesModified.length} file(s)`, {
139
- files: result.filesModified,
140
- });
141
-
142
- // Empty diff is a no-op success
143
- if (!validation.output.diff || validation.output.diff.trim() === '') {
144
- options.onProgress?.('done', 'No changes to apply');
145
- result.success = true;
146
- result.stage = 'done';
147
- result.duration = Date.now() - startTime;
148
- return result;
149
- }
150
-
151
- // Step 3: Fingerprint repo
152
- result.stage = 'fingerprint';
153
- options.onProgress?.('fingerprint', 'Analyzing project structure');
154
-
155
- const { fingerprint, detectionNotes } = fingerprintRepo(options.projectPath);
156
- result.fingerprint = fingerprint;
157
- result.warnings.push(...detectionNotes);
158
-
159
- options.onProgress?.('fingerprint', `Detected ${fingerprint.framework} + ${fingerprint.packageManager}`, {
160
- fingerprint,
161
- });
162
-
163
- // Dry run: stop here and report what would happen
164
- if (options.dryRun) {
165
- options.onProgress?.('done', 'Dry run complete - no changes applied');
166
- result.success = true;
167
- result.stage = 'done';
168
- result.duration = Date.now() - startTime;
169
- return result;
170
- }
171
-
172
- // Step 4: Create temp workspace
173
- result.stage = 'workspace';
174
- options.onProgress?.('workspace', 'Creating isolated workspace');
175
-
176
- const workspaceInfo = await this.workspace.create({
177
- projectPath: options.projectPath,
178
- useWorktree: true,
179
- installDeps: false, // Don't install deps in workspace for speed
180
- timeout: options.timeout,
181
- });
182
- workspaceId = workspaceInfo.id;
183
-
184
- options.onProgress?.('workspace', `Created ${workspaceInfo.type} workspace`, {
185
- path: workspaceInfo.path,
186
- });
187
-
188
- // Step 5: Apply diff
189
- result.stage = 'apply';
190
- options.onProgress?.('apply', 'Applying diff to workspace');
191
-
192
- const applyResult = await this.workspace.applyDiff(
193
- workspaceInfo.path,
194
- validation.output.diff,
195
- validation.diffValidation?.hunks || []
196
- );
197
-
198
- if (!applyResult.success) {
199
- result.errors.push(...applyResult.errors);
200
- throw new Error(`Diff application failed: ${applyResult.errors.join('; ')}`);
201
- }
202
-
203
- options.onProgress?.('apply', `Applied ${applyResult.applied} hunk(s)`);
204
-
205
- // Step 6-8: Run verification (typecheck, build, tests)
206
- result.stage = 'typecheck';
207
- options.onProgress?.('typecheck', 'Running verification checks');
208
-
209
- const verification = await this.workspace.verify(
210
- workspaceInfo.path,
211
- fingerprint,
212
- {
213
- skipTests: options.skipTests,
214
- timeout: options.timeout,
215
- }
216
- );
217
- result.verification = verification;
218
- result.failureContext = verification.failureContext;
219
-
220
- // Report check progress
221
- for (const check of verification.checks) {
222
- const status = check.passed ? '✓' : '✗';
223
- const stage = check.name.toLowerCase().includes('build') ? 'build' :
224
- check.name.toLowerCase().includes('test') ? 'test' : 'typecheck';
225
- options.onProgress?.(stage as PipelineStage, `${status} ${check.name} (${check.duration}ms)`);
226
- }
227
-
228
- if (!verification.passed) {
229
- result.errors.push('Verification failed');
230
- result.errors.push(...verification.failureContext);
231
- throw new Error(`Verification failed: ${verification.failureContext.slice(0, 3).join('; ')}`);
232
- }
233
-
234
- // Step 9: Copy verified changes back to project
235
- result.stage = 'commit';
236
- options.onProgress?.('commit', 'Applying verified changes to project');
237
-
238
- await this.workspace.copyBack(
239
- workspaceInfo.path,
240
- options.projectPath,
241
- result.filesModified
242
- );
243
-
244
- // Track usage
245
- await trackUsage('fixRuns', 1);
246
-
247
- // Success!
248
- result.success = true;
249
- result.stage = 'done';
250
- options.onProgress?.('done', `Successfully modified ${result.filesModified.length} file(s)`);
251
-
252
- } catch (e) {
253
- const error = e as Error & { code?: string };
254
- result.errors.push(error.message);
255
-
256
- // Handle entitlement errors
257
- if (error.code === 'FEATURE_NOT_AVAILABLE') {
258
- result.stage = 'error';
259
- result.errors = [`Feature requires upgrade: ${error.message}`];
260
- }
261
-
262
- options.onProgress?.('error', error.message);
263
- } finally {
264
- // Cleanup workspace
265
- if (workspaceId) {
266
- try {
267
- await this.workspace.cleanup(workspaceId);
268
- } catch {
269
- // Ignore cleanup errors
270
- }
271
- }
272
-
273
- result.duration = Date.now() - startTime;
274
- }
275
-
276
- return result;
277
- }
278
-
279
- /**
280
- * Run from a file (CLI convenience method)
281
- */
282
- async runFromFile(
283
- agentOutputFile: string,
284
- projectPath: string,
285
- options?: Partial<PipelineOptions>
286
- ): Promise<PipelineResult> {
287
- return this.run({
288
- projectPath,
289
- agentOutputFile,
290
- ...options,
291
- });
292
- }
293
-
294
- /**
295
- * Validate only (no apply) - for checking output format
296
- */
297
- validateOnly(raw: string, projectPath: string): FullValidationResult {
298
- return validateAgentOutput(raw, projectPath);
299
- }
300
- }
301
-
302
- // ============================================================================
303
- // RESULT FORMATTING
304
- // ============================================================================
305
-
306
- /**
307
- * Format pipeline result for CLI output
308
- */
309
- export function formatPipelineResult(result: PipelineResult): string {
310
- const lines: string[] = [];
311
-
312
- // Header
313
- if (result.success) {
314
- lines.push('✓ VERIFIED AUTOFIX SUCCESSFUL');
315
- } else {
316
- lines.push('✗ VERIFIED AUTOFIX FAILED');
317
- }
318
- lines.push('');
319
-
320
- // Stage info
321
- lines.push(`Stage: ${result.stage}`);
322
- lines.push(`Duration: ${result.duration}ms`);
323
- lines.push('');
324
-
325
- // Files modified
326
- if (result.filesModified.length > 0) {
327
- lines.push('Files modified:');
328
- for (const file of result.filesModified.slice(0, 10)) {
329
- lines.push(` • ${file}`);
330
- }
331
- if (result.filesModified.length > 10) {
332
- lines.push(` ... and ${result.filesModified.length - 10} more`);
333
- }
334
- lines.push('');
335
- }
336
-
337
- // Verification results
338
- if (result.verification) {
339
- lines.push('Verification:');
340
- for (const check of result.verification.checks) {
341
- const icon = check.passed ? '✓' : '✗';
342
- lines.push(` ${icon} ${check.name} (${check.duration}ms)`);
343
- }
344
- lines.push('');
345
- }
346
-
347
- // Errors
348
- if (result.errors.length > 0) {
349
- lines.push('Errors:');
350
- for (const err of result.errors.slice(0, 5)) {
351
- lines.push(` • ${err}`);
352
- }
353
- lines.push('');
354
- }
355
-
356
- // Failure context (top 3)
357
- if (result.failureContext.length > 0) {
358
- lines.push('Top failures:');
359
- for (const ctx of result.failureContext) {
360
- lines.push(` 1. ${ctx}`);
361
- }
362
- lines.push('');
363
- }
364
-
365
- // Warnings
366
- if (result.warnings.length > 0) {
367
- lines.push('Warnings:');
368
- for (const warn of result.warnings.slice(0, 5)) {
369
- lines.push(` ⚠ ${warn}`);
370
- }
371
- }
372
-
373
- return lines.join('\n');
374
- }
375
-
376
- /**
377
- * Format result as JSON for machine consumption
378
- */
379
- export function formatPipelineResultJson(result: PipelineResult): string {
380
- return JSON.stringify({
381
- success: result.success,
382
- stage: result.stage,
383
- duration: result.duration,
384
- filesModified: result.filesModified,
385
- errors: result.errors,
386
- warnings: result.warnings,
387
- failureContext: result.failureContext,
388
- verification: result.verification ? {
389
- passed: result.verification.passed,
390
- checks: result.verification.checks.map(c => ({
391
- name: c.name,
392
- passed: c.passed,
393
- duration: c.duration,
394
- })),
395
- } : null,
396
- }, null, 2);
397
- }
398
-
399
- // ============================================================================
400
- // EXPORTS
401
- // ============================================================================
402
-
403
- export const verifiedAutofixPipeline = new VerifiedAutofixPipeline();