@rigour-labs/core 2.17.2 → 2.18.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.
- package/dist/context.test.js +15 -1
- package/dist/discovery.js +14 -1
- package/dist/discovery.test.js +23 -0
- package/dist/gates/agent-team.d.ts +50 -0
- package/dist/gates/agent-team.js +159 -0
- package/dist/gates/agent-team.test.d.ts +1 -0
- package/dist/gates/agent-team.test.js +113 -0
- package/dist/gates/checkpoint.d.ts +72 -0
- package/dist/gates/checkpoint.js +231 -0
- package/dist/gates/checkpoint.test.d.ts +1 -0
- package/dist/gates/checkpoint.test.js +102 -0
- package/dist/gates/context.d.ts +35 -0
- package/dist/gates/context.js +151 -2
- package/dist/gates/runner.js +15 -0
- package/dist/gates/security-patterns.d.ts +48 -0
- package/dist/gates/security-patterns.js +236 -0
- package/dist/gates/security-patterns.test.d.ts +1 -0
- package/dist/gates/security-patterns.test.js +133 -0
- package/dist/services/adaptive-thresholds.d.ts +63 -0
- package/dist/services/adaptive-thresholds.js +204 -0
- package/dist/services/adaptive-thresholds.test.d.ts +1 -0
- package/dist/services/adaptive-thresholds.test.js +129 -0
- package/dist/templates/index.d.ts +1 -0
- package/dist/templates/index.js +81 -0
- package/dist/types/fix-packet.d.ts +4 -4
- package/dist/types/index.d.ts +404 -0
- package/dist/types/index.js +36 -0
- package/package.json +1 -1
- package/src/context.test.ts +15 -1
- package/src/discovery.test.ts +27 -0
- package/src/discovery.ts +15 -2
- package/src/gates/agent-team.test.ts +134 -0
- package/src/gates/agent-team.ts +210 -0
- package/src/gates/checkpoint.test.ts +135 -0
- package/src/gates/checkpoint.ts +311 -0
- package/src/gates/context.ts +200 -2
- package/src/gates/runner.ts +18 -0
- package/src/gates/security-patterns.test.ts +162 -0
- package/src/gates/security-patterns.ts +303 -0
- package/src/services/adaptive-thresholds.test.ts +189 -0
- package/src/services/adaptive-thresholds.ts +275 -0
- package/src/templates/index.ts +82 -0
- package/src/types/index.ts +36 -0
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import { detectComplexityTier, calculateAdaptiveThresholds, recordGateRun, getQualityTrend, clearAdaptiveHistory, getAdaptiveSummary, } from './adaptive-thresholds.js';
|
|
3
|
+
import * as fs from 'fs';
|
|
4
|
+
import * as path from 'path';
|
|
5
|
+
import * as os from 'os';
|
|
6
|
+
describe('AdaptiveThresholds', () => {
|
|
7
|
+
let testDir;
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
testDir = fs.mkdtempSync(path.join(os.tmpdir(), 'adaptive-test-'));
|
|
10
|
+
});
|
|
11
|
+
afterEach(() => {
|
|
12
|
+
clearAdaptiveHistory(testDir);
|
|
13
|
+
fs.rmSync(testDir, { recursive: true, force: true });
|
|
14
|
+
});
|
|
15
|
+
describe('detectComplexityTier', () => {
|
|
16
|
+
it('should detect hobby tier for small projects', () => {
|
|
17
|
+
const tier = detectComplexityTier({ fileCount: 20 });
|
|
18
|
+
expect(tier).toBe('hobby');
|
|
19
|
+
});
|
|
20
|
+
it('should detect startup tier for medium projects', () => {
|
|
21
|
+
const tier = detectComplexityTier({ fileCount: 100 });
|
|
22
|
+
expect(tier).toBe('startup');
|
|
23
|
+
});
|
|
24
|
+
it('should detect enterprise tier for large projects', () => {
|
|
25
|
+
const tier = detectComplexityTier({ fileCount: 600 });
|
|
26
|
+
expect(tier).toBe('enterprise');
|
|
27
|
+
});
|
|
28
|
+
it('should consider commit count for tier detection', () => {
|
|
29
|
+
const tier = detectComplexityTier({ fileCount: 50, commitCount: 1500 });
|
|
30
|
+
expect(tier).toBe('enterprise');
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
describe('calculateAdaptiveThresholds', () => {
|
|
34
|
+
it('should return lenient thresholds for hobby tier', () => {
|
|
35
|
+
const adjustments = calculateAdaptiveThresholds(testDir, { fileCount: 20 });
|
|
36
|
+
expect(adjustments.tier).toBe('hobby');
|
|
37
|
+
expect(adjustments.coverageThreshold).toBeLessThan(80);
|
|
38
|
+
expect(adjustments.securityBlockLevel).toBe('critical');
|
|
39
|
+
expect(adjustments.leniencyFactor).toBeGreaterThan(0.5);
|
|
40
|
+
});
|
|
41
|
+
it('should return strict thresholds for enterprise tier', () => {
|
|
42
|
+
const adjustments = calculateAdaptiveThresholds(testDir, { fileCount: 600 });
|
|
43
|
+
expect(adjustments.tier).toBe('enterprise');
|
|
44
|
+
expect(adjustments.coverageThreshold).toBe(80);
|
|
45
|
+
expect(adjustments.securityBlockLevel).toBe('medium');
|
|
46
|
+
expect(adjustments.leniencyFactor).toBeLessThan(0.5);
|
|
47
|
+
});
|
|
48
|
+
it('should respect forced_tier config', () => {
|
|
49
|
+
const adjustments = calculateAdaptiveThresholds(testDir, { fileCount: 20 }, { forced_tier: 'enterprise' });
|
|
50
|
+
expect(adjustments.tier).toBe('enterprise');
|
|
51
|
+
});
|
|
52
|
+
it('should include reasoning for adjustments', () => {
|
|
53
|
+
const adjustments = calculateAdaptiveThresholds(testDir, { fileCount: 100 });
|
|
54
|
+
expect(adjustments.reasoning.length).toBeGreaterThan(0);
|
|
55
|
+
expect(adjustments.reasoning.some(r => r.includes('tier'))).toBe(true);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
describe('historical tracking', () => {
|
|
59
|
+
it('should record gate runs', () => {
|
|
60
|
+
recordGateRun(testDir, 5, 2, 10);
|
|
61
|
+
recordGateRun(testDir, 6, 1, 5);
|
|
62
|
+
const historyPath = path.join(testDir, '.rigour', 'adaptive-history.json');
|
|
63
|
+
expect(fs.existsSync(historyPath)).toBe(true);
|
|
64
|
+
const history = JSON.parse(fs.readFileSync(historyPath, 'utf-8'));
|
|
65
|
+
expect(history.runs).toHaveLength(2);
|
|
66
|
+
});
|
|
67
|
+
it('should return stable trend for new projects', () => {
|
|
68
|
+
const trend = getQualityTrend(testDir);
|
|
69
|
+
expect(trend).toBe('stable');
|
|
70
|
+
});
|
|
71
|
+
it('should detect improving trend', () => {
|
|
72
|
+
// Record 20 runs: older ones with high failures, recent with low
|
|
73
|
+
for (let i = 0; i < 10; i++) {
|
|
74
|
+
recordGateRun(testDir, 3, 5, 20);
|
|
75
|
+
}
|
|
76
|
+
for (let i = 0; i < 10; i++) {
|
|
77
|
+
recordGateRun(testDir, 7, 1, 5);
|
|
78
|
+
}
|
|
79
|
+
const trend = getQualityTrend(testDir);
|
|
80
|
+
expect(trend).toBe('improving');
|
|
81
|
+
});
|
|
82
|
+
it('should detect degrading trend', () => {
|
|
83
|
+
// Record 20 runs: older ones with low failures, recent with high
|
|
84
|
+
for (let i = 0; i < 10; i++) {
|
|
85
|
+
recordGateRun(testDir, 7, 1, 3);
|
|
86
|
+
}
|
|
87
|
+
for (let i = 0; i < 10; i++) {
|
|
88
|
+
recordGateRun(testDir, 3, 5, 20);
|
|
89
|
+
}
|
|
90
|
+
const trend = getQualityTrend(testDir);
|
|
91
|
+
expect(trend).toBe('degrading');
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
describe('trend-based adjustments', () => {
|
|
95
|
+
it('should relax thresholds for improving trend', () => {
|
|
96
|
+
// Create improving history
|
|
97
|
+
for (let i = 0; i < 10; i++) {
|
|
98
|
+
recordGateRun(testDir, 3, 5, 20);
|
|
99
|
+
}
|
|
100
|
+
for (let i = 0; i < 10; i++) {
|
|
101
|
+
recordGateRun(testDir, 7, 1, 5);
|
|
102
|
+
}
|
|
103
|
+
const adjustments = calculateAdaptiveThresholds(testDir, { fileCount: 100 });
|
|
104
|
+
expect(adjustments.trend).toBe('improving');
|
|
105
|
+
expect(adjustments.reasoning.some(r => r.includes('bonus'))).toBe(true);
|
|
106
|
+
});
|
|
107
|
+
it('should tighten thresholds for degrading trend', () => {
|
|
108
|
+
// Create degrading history
|
|
109
|
+
for (let i = 0; i < 10; i++) {
|
|
110
|
+
recordGateRun(testDir, 7, 1, 3);
|
|
111
|
+
}
|
|
112
|
+
for (let i = 0; i < 10; i++) {
|
|
113
|
+
recordGateRun(testDir, 3, 5, 20);
|
|
114
|
+
}
|
|
115
|
+
const adjustments = calculateAdaptiveThresholds(testDir, { fileCount: 100 });
|
|
116
|
+
expect(adjustments.trend).toBe('degrading');
|
|
117
|
+
expect(adjustments.reasoning.some(r => r.includes('tightened'))).toBe(true);
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
describe('getAdaptiveSummary', () => {
|
|
121
|
+
it('should return formatted summary string', () => {
|
|
122
|
+
const adjustments = calculateAdaptiveThresholds(testDir, { fileCount: 100 });
|
|
123
|
+
const summary = getAdaptiveSummary(adjustments);
|
|
124
|
+
expect(summary).toContain('STARTUP');
|
|
125
|
+
expect(summary).toContain('Coverage:');
|
|
126
|
+
expect(summary).toContain('Quality:');
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
});
|
package/dist/templates/index.js
CHANGED
|
@@ -14,6 +14,17 @@ export const TEMPLATES = [
|
|
|
14
14
|
],
|
|
15
15
|
config: {
|
|
16
16
|
preset: 'ui',
|
|
17
|
+
ignore: [
|
|
18
|
+
'.git/**',
|
|
19
|
+
'node_modules/**',
|
|
20
|
+
'dist/**',
|
|
21
|
+
'build/**',
|
|
22
|
+
'.next/**',
|
|
23
|
+
'.nuxt/**',
|
|
24
|
+
'.svelte-kit/**',
|
|
25
|
+
'coverage/**',
|
|
26
|
+
'.turbo/**',
|
|
27
|
+
],
|
|
17
28
|
gates: {
|
|
18
29
|
max_file_lines: 300,
|
|
19
30
|
required_files: ['docs/SPEC.md', 'docs/ARCH.md', 'README.md'],
|
|
@@ -39,6 +50,23 @@ export const TEMPLATES = [
|
|
|
39
50
|
],
|
|
40
51
|
config: {
|
|
41
52
|
preset: 'api',
|
|
53
|
+
ignore: [
|
|
54
|
+
'.git/**',
|
|
55
|
+
// Node.js
|
|
56
|
+
'node_modules/**',
|
|
57
|
+
'dist/**',
|
|
58
|
+
// Python
|
|
59
|
+
'venv/**',
|
|
60
|
+
'.venv/**',
|
|
61
|
+
'__pycache__/**',
|
|
62
|
+
'*.pyc',
|
|
63
|
+
'.tox/**',
|
|
64
|
+
'.pytest_cache/**',
|
|
65
|
+
'.mypy_cache/**',
|
|
66
|
+
'*.egg-info/**',
|
|
67
|
+
// Go
|
|
68
|
+
'vendor/**',
|
|
69
|
+
],
|
|
42
70
|
gates: {
|
|
43
71
|
max_file_lines: 400,
|
|
44
72
|
required_files: ['docs/SPEC.md', 'docs/ARCH.md', 'README.md'],
|
|
@@ -61,6 +89,14 @@ export const TEMPLATES = [
|
|
|
61
89
|
],
|
|
62
90
|
config: {
|
|
63
91
|
preset: 'infra',
|
|
92
|
+
ignore: [
|
|
93
|
+
'.git/**',
|
|
94
|
+
'.terraform/**',
|
|
95
|
+
'*.tfstate',
|
|
96
|
+
'*.tfstate.backup',
|
|
97
|
+
'.terragrunt-cache/**',
|
|
98
|
+
'charts/**/*.tgz',
|
|
99
|
+
],
|
|
64
100
|
gates: {
|
|
65
101
|
max_file_lines: 300,
|
|
66
102
|
required_files: ['docs/RUNBOOK.md', 'docs/ARCH.md', 'README.md'],
|
|
@@ -78,6 +114,17 @@ export const TEMPLATES = [
|
|
|
78
114
|
],
|
|
79
115
|
config: {
|
|
80
116
|
preset: 'data',
|
|
117
|
+
ignore: [
|
|
118
|
+
'.git/**',
|
|
119
|
+
'.ipynb_checkpoints/**',
|
|
120
|
+
'__pycache__/**',
|
|
121
|
+
'*.pyc',
|
|
122
|
+
'dbt_packages/**',
|
|
123
|
+
'target/**',
|
|
124
|
+
'logs/**',
|
|
125
|
+
'*.parquet',
|
|
126
|
+
'*.csv',
|
|
127
|
+
],
|
|
81
128
|
gates: {
|
|
82
129
|
max_file_lines: 500,
|
|
83
130
|
required_files: ['docs/DATA_DICTIONARY.md', 'docs/PIPELINE.md', 'README.md'],
|
|
@@ -179,6 +226,10 @@ export const UNIVERSAL_CONFIG = {
|
|
|
179
226
|
sensitivity: 0.8,
|
|
180
227
|
mining_depth: 100,
|
|
181
228
|
ignored_patterns: [],
|
|
229
|
+
cross_file_patterns: true,
|
|
230
|
+
naming_consistency: true,
|
|
231
|
+
import_relationships: true,
|
|
232
|
+
max_cross_file_depth: 50,
|
|
182
233
|
},
|
|
183
234
|
environment: {
|
|
184
235
|
enabled: true,
|
|
@@ -192,6 +243,36 @@ export const UNIVERSAL_CONFIG = {
|
|
|
192
243
|
auto_classify: true,
|
|
193
244
|
doc_sources: {},
|
|
194
245
|
},
|
|
246
|
+
agent_team: {
|
|
247
|
+
enabled: false,
|
|
248
|
+
max_concurrent_agents: 3,
|
|
249
|
+
cross_agent_pattern_check: true,
|
|
250
|
+
handoff_verification: true,
|
|
251
|
+
task_ownership: 'strict',
|
|
252
|
+
},
|
|
253
|
+
checkpoint: {
|
|
254
|
+
enabled: false,
|
|
255
|
+
interval_minutes: 15,
|
|
256
|
+
quality_threshold: 80,
|
|
257
|
+
drift_detection: true,
|
|
258
|
+
auto_save_on_failure: true,
|
|
259
|
+
},
|
|
260
|
+
security: {
|
|
261
|
+
enabled: false,
|
|
262
|
+
sql_injection: true,
|
|
263
|
+
xss: true,
|
|
264
|
+
path_traversal: true,
|
|
265
|
+
hardcoded_secrets: true,
|
|
266
|
+
insecure_randomness: true,
|
|
267
|
+
command_injection: true,
|
|
268
|
+
block_on_severity: 'high',
|
|
269
|
+
},
|
|
270
|
+
adaptive: {
|
|
271
|
+
enabled: false,
|
|
272
|
+
base_coverage_threshold: 80,
|
|
273
|
+
base_quality_threshold: 80,
|
|
274
|
+
auto_detect_tier: true,
|
|
275
|
+
},
|
|
195
276
|
staleness: {
|
|
196
277
|
enabled: false,
|
|
197
278
|
rules: {
|
|
@@ -22,7 +22,7 @@ export declare const FixPacketV2Schema: z.ZodObject<{
|
|
|
22
22
|
title: string;
|
|
23
23
|
details: string;
|
|
24
24
|
gate: string;
|
|
25
|
-
severity: "
|
|
25
|
+
severity: "critical" | "high" | "medium" | "low";
|
|
26
26
|
files?: string[] | undefined;
|
|
27
27
|
hint?: string | undefined;
|
|
28
28
|
category?: string | undefined;
|
|
@@ -36,7 +36,7 @@ export declare const FixPacketV2Schema: z.ZodObject<{
|
|
|
36
36
|
files?: string[] | undefined;
|
|
37
37
|
hint?: string | undefined;
|
|
38
38
|
category?: string | undefined;
|
|
39
|
-
severity?: "
|
|
39
|
+
severity?: "critical" | "high" | "medium" | "low" | undefined;
|
|
40
40
|
instructions?: string[] | undefined;
|
|
41
41
|
metrics?: Record<string, any> | undefined;
|
|
42
42
|
}>, "many">;
|
|
@@ -70,7 +70,7 @@ export declare const FixPacketV2Schema: z.ZodObject<{
|
|
|
70
70
|
title: string;
|
|
71
71
|
details: string;
|
|
72
72
|
gate: string;
|
|
73
|
-
severity: "
|
|
73
|
+
severity: "critical" | "high" | "medium" | "low";
|
|
74
74
|
files?: string[] | undefined;
|
|
75
75
|
hint?: string | undefined;
|
|
76
76
|
category?: string | undefined;
|
|
@@ -95,7 +95,7 @@ export declare const FixPacketV2Schema: z.ZodObject<{
|
|
|
95
95
|
files?: string[] | undefined;
|
|
96
96
|
hint?: string | undefined;
|
|
97
97
|
category?: string | undefined;
|
|
98
|
-
severity?: "
|
|
98
|
+
severity?: "critical" | "high" | "medium" | "low" | undefined;
|
|
99
99
|
instructions?: string[] | undefined;
|
|
100
100
|
metrics?: Record<string, any> | undefined;
|
|
101
101
|
}[];
|