@rigour-labs/core 2.21.2 → 2.22.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.
- package/dist/gates/base.d.ts +2 -2
- package/dist/gates/base.js +2 -1
- package/dist/gates/content.js +1 -1
- package/dist/gates/context-window-artifacts.d.ts +33 -0
- package/dist/gates/context-window-artifacts.js +211 -0
- package/dist/gates/context.js +3 -3
- package/dist/gates/duplication-drift.d.ts +32 -0
- package/dist/gates/duplication-drift.js +187 -0
- package/dist/gates/file.js +1 -1
- package/dist/gates/hallucinated-imports.d.ts +44 -0
- package/dist/gates/hallucinated-imports.js +292 -0
- package/dist/gates/inconsistent-error-handling.d.ts +38 -0
- package/dist/gates/inconsistent-error-handling.js +222 -0
- package/dist/gates/runner.js +29 -1
- package/dist/gates/security-patterns.js +1 -1
- package/dist/templates/index.js +26 -0
- package/dist/types/fix-packet.d.ts +4 -4
- package/dist/types/index.d.ts +277 -0
- package/dist/types/index.js +38 -0
- package/package.json +1 -1
- package/src/gates/base.ts +3 -2
- package/src/gates/content.ts +2 -1
- package/src/gates/context-window-artifacts.ts +277 -0
- package/src/gates/context.ts +6 -3
- package/src/gates/duplication-drift.ts +231 -0
- package/src/gates/file.ts +5 -1
- package/src/gates/hallucinated-imports.ts +361 -0
- package/src/gates/inconsistent-error-handling.ts +254 -0
- package/src/gates/runner.ts +34 -2
- package/src/gates/security-patterns.ts +2 -1
- package/src/templates/index.ts +26 -0
- package/src/types/index.ts +41 -0
package/src/gates/runner.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Gate } from './base.js';
|
|
2
|
-
import { Failure, Config, Report, Status } from '../types/index.js';
|
|
2
|
+
import { Failure, Config, Report, Status, Severity, SEVERITY_WEIGHTS } from '../types/index.js';
|
|
3
3
|
import { FileGate } from './file.js';
|
|
4
4
|
import { ContentGate } from './content.js';
|
|
5
5
|
import { StructureGate } from './structure.js';
|
|
@@ -14,6 +14,10 @@ import { RetryLoopBreakerGate } from './retry-loop-breaker.js';
|
|
|
14
14
|
import { AgentTeamGate } from './agent-team.js';
|
|
15
15
|
import { CheckpointGate } from './checkpoint.js';
|
|
16
16
|
import { SecurityPatternsGate } from './security-patterns.js';
|
|
17
|
+
import { DuplicationDriftGate } from './duplication-drift.js';
|
|
18
|
+
import { HallucinatedImportsGate } from './hallucinated-imports.js';
|
|
19
|
+
import { InconsistentErrorHandlingGate } from './inconsistent-error-handling.js';
|
|
20
|
+
import { ContextWindowArtifactsGate } from './context-window-artifacts.js';
|
|
17
21
|
import { execa } from 'execa';
|
|
18
22
|
import { Logger } from '../utils/logger.js';
|
|
19
23
|
|
|
@@ -66,6 +70,23 @@ export class GateRunner {
|
|
|
66
70
|
this.gates.push(new SecurityPatternsGate(this.config.gates.security));
|
|
67
71
|
}
|
|
68
72
|
|
|
73
|
+
// v2.16+ AI-Native Drift Detection Gates (enabled by default)
|
|
74
|
+
if (this.config.gates.duplication_drift?.enabled !== false) {
|
|
75
|
+
this.gates.push(new DuplicationDriftGate(this.config.gates.duplication_drift));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (this.config.gates.hallucinated_imports?.enabled !== false) {
|
|
79
|
+
this.gates.push(new HallucinatedImportsGate(this.config.gates.hallucinated_imports));
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (this.config.gates.inconsistent_error_handling?.enabled !== false) {
|
|
83
|
+
this.gates.push(new InconsistentErrorHandlingGate(this.config.gates.inconsistent_error_handling));
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (this.config.gates.context_window_artifacts?.enabled !== false) {
|
|
87
|
+
this.gates.push(new ContextWindowArtifactsGate(this.config.gates.context_window_artifacts));
|
|
88
|
+
}
|
|
89
|
+
|
|
69
90
|
// Environment Alignment Gate (Should be prioritized)
|
|
70
91
|
if (this.config.gates.environment?.enabled) {
|
|
71
92
|
this.gates.unshift(new EnvironmentGate(this.config.gates));
|
|
@@ -141,7 +162,17 @@ export class GateRunner {
|
|
|
141
162
|
}
|
|
142
163
|
|
|
143
164
|
const status: Status = failures.length > 0 ? 'FAIL' : 'PASS';
|
|
144
|
-
|
|
165
|
+
|
|
166
|
+
// Severity-weighted scoring: each failure deducts based on its severity
|
|
167
|
+
// critical=20, high=10, medium=5, low=2, info=0
|
|
168
|
+
const severityBreakdown: Record<string, number> = {};
|
|
169
|
+
let totalDeduction = 0;
|
|
170
|
+
for (const f of failures) {
|
|
171
|
+
const sev = (f.severity || 'medium') as Severity;
|
|
172
|
+
severityBreakdown[sev] = (severityBreakdown[sev] || 0) + 1;
|
|
173
|
+
totalDeduction += SEVERITY_WEIGHTS[sev] ?? 5;
|
|
174
|
+
}
|
|
175
|
+
const score = Math.max(0, 100 - totalDeduction);
|
|
145
176
|
|
|
146
177
|
return {
|
|
147
178
|
status,
|
|
@@ -150,6 +181,7 @@ export class GateRunner {
|
|
|
150
181
|
stats: {
|
|
151
182
|
duration_ms: Date.now() - start,
|
|
152
183
|
score,
|
|
184
|
+
severity_breakdown: severityBreakdown,
|
|
153
185
|
},
|
|
154
186
|
};
|
|
155
187
|
}
|
|
@@ -236,7 +236,8 @@ export class SecurityPatternsGate extends Gate {
|
|
|
236
236
|
`Found: "${vuln.match.slice(0, 60)}..." - Use parameterized queries/sanitization.`,
|
|
237
237
|
`Security: ${vuln.type.replace('_', ' ').toUpperCase()}`,
|
|
238
238
|
vuln.line,
|
|
239
|
-
vuln.line
|
|
239
|
+
vuln.line,
|
|
240
|
+
vuln.severity
|
|
240
241
|
));
|
|
241
242
|
}
|
|
242
243
|
}
|
package/src/templates/index.ts
CHANGED
|
@@ -303,6 +303,32 @@ export const UNIVERSAL_CONFIG: Config = {
|
|
|
303
303
|
'prefer-const': false,
|
|
304
304
|
},
|
|
305
305
|
},
|
|
306
|
+
duplication_drift: {
|
|
307
|
+
enabled: true,
|
|
308
|
+
similarity_threshold: 0.8,
|
|
309
|
+
min_body_lines: 5,
|
|
310
|
+
},
|
|
311
|
+
hallucinated_imports: {
|
|
312
|
+
enabled: true,
|
|
313
|
+
check_relative: true,
|
|
314
|
+
check_packages: true,
|
|
315
|
+
ignore_patterns: [
|
|
316
|
+
'\\.css$', '\\.scss$', '\\.less$', '\\.svg$', '\\.png$', '\\.jpg$',
|
|
317
|
+
'\\.json$', '\\.wasm$', '\\.graphql$', '\\.gql$',
|
|
318
|
+
],
|
|
319
|
+
},
|
|
320
|
+
inconsistent_error_handling: {
|
|
321
|
+
enabled: true,
|
|
322
|
+
max_strategies_per_type: 2,
|
|
323
|
+
min_occurrences: 3,
|
|
324
|
+
ignore_empty_catches: false,
|
|
325
|
+
},
|
|
326
|
+
context_window_artifacts: {
|
|
327
|
+
enabled: true,
|
|
328
|
+
min_file_lines: 100,
|
|
329
|
+
degradation_threshold: 0.4,
|
|
330
|
+
signals_required: 2,
|
|
331
|
+
},
|
|
306
332
|
},
|
|
307
333
|
output: {
|
|
308
334
|
report_path: 'rigour-report.json',
|
package/src/types/index.ts
CHANGED
|
@@ -103,6 +103,33 @@ export const GatesSchema = z.object({
|
|
|
103
103
|
auto_detect_tier: z.boolean().optional().default(true),
|
|
104
104
|
forced_tier: z.enum(['hobby', 'startup', 'enterprise']).optional(),
|
|
105
105
|
}).optional().default({}),
|
|
106
|
+
// v2.16+ AI-Native Drift Detection Gates
|
|
107
|
+
duplication_drift: z.object({
|
|
108
|
+
enabled: z.boolean().optional().default(true),
|
|
109
|
+
similarity_threshold: z.number().min(0).max(1).optional().default(0.8),
|
|
110
|
+
min_body_lines: z.number().optional().default(5),
|
|
111
|
+
}).optional().default({}),
|
|
112
|
+
hallucinated_imports: z.object({
|
|
113
|
+
enabled: z.boolean().optional().default(true),
|
|
114
|
+
check_relative: z.boolean().optional().default(true),
|
|
115
|
+
check_packages: z.boolean().optional().default(true),
|
|
116
|
+
ignore_patterns: z.array(z.string()).optional().default([
|
|
117
|
+
'\\.css$', '\\.scss$', '\\.less$', '\\.svg$', '\\.png$', '\\.jpg$',
|
|
118
|
+
'\\.json$', '\\.wasm$', '\\.graphql$', '\\.gql$',
|
|
119
|
+
]),
|
|
120
|
+
}).optional().default({}),
|
|
121
|
+
inconsistent_error_handling: z.object({
|
|
122
|
+
enabled: z.boolean().optional().default(true),
|
|
123
|
+
max_strategies_per_type: z.number().optional().default(2),
|
|
124
|
+
min_occurrences: z.number().optional().default(3),
|
|
125
|
+
ignore_empty_catches: z.boolean().optional().default(false),
|
|
126
|
+
}).optional().default({}),
|
|
127
|
+
context_window_artifacts: z.object({
|
|
128
|
+
enabled: z.boolean().optional().default(true),
|
|
129
|
+
min_file_lines: z.number().optional().default(100),
|
|
130
|
+
degradation_threshold: z.number().min(0).max(1).optional().default(0.4),
|
|
131
|
+
signals_required: z.number().optional().default(2),
|
|
132
|
+
}).optional().default({}),
|
|
106
133
|
});
|
|
107
134
|
|
|
108
135
|
export const CommandsSchema = z.object({
|
|
@@ -136,10 +163,23 @@ export type RawConfig = z.input<typeof ConfigSchema>;
|
|
|
136
163
|
export const StatusSchema = z.enum(['PASS', 'FAIL', 'SKIP', 'ERROR']);
|
|
137
164
|
export type Status = z.infer<typeof StatusSchema>;
|
|
138
165
|
|
|
166
|
+
export const SeveritySchema = z.enum(['critical', 'high', 'medium', 'low', 'info']);
|
|
167
|
+
export type Severity = z.infer<typeof SeveritySchema>;
|
|
168
|
+
|
|
169
|
+
/** Severity weights for score calculation */
|
|
170
|
+
export const SEVERITY_WEIGHTS: Record<Severity, number> = {
|
|
171
|
+
critical: 20,
|
|
172
|
+
high: 10,
|
|
173
|
+
medium: 5,
|
|
174
|
+
low: 2,
|
|
175
|
+
info: 0,
|
|
176
|
+
};
|
|
177
|
+
|
|
139
178
|
export const FailureSchema = z.object({
|
|
140
179
|
id: z.string(),
|
|
141
180
|
title: z.string(),
|
|
142
181
|
details: z.string(),
|
|
182
|
+
severity: SeveritySchema.optional(),
|
|
143
183
|
files: z.array(z.string()).optional(),
|
|
144
184
|
line: z.number().optional(),
|
|
145
185
|
endLine: z.number().optional(),
|
|
@@ -154,6 +194,7 @@ export const ReportSchema = z.object({
|
|
|
154
194
|
stats: z.object({
|
|
155
195
|
duration_ms: z.number(),
|
|
156
196
|
score: z.number().optional(),
|
|
197
|
+
severity_breakdown: z.record(z.number()).optional(),
|
|
157
198
|
}),
|
|
158
199
|
});
|
|
159
200
|
export type Report = z.infer<typeof ReportSchema>;
|