@rigour-labs/core 5.0.1 → 5.1.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/README.md +9 -1
- package/dist/gates/agent-team.d.ts +0 -1
- package/dist/gates/agent-team.js +0 -1
- package/dist/gates/checkpoint.d.ts +0 -2
- package/dist/gates/checkpoint.js +0 -2
- package/dist/gates/context-window-artifacts.d.ts +6 -2
- package/dist/gates/context-window-artifacts.js +107 -31
- package/dist/gates/deep-analysis.d.ts +2 -0
- package/dist/gates/deep-analysis.js +41 -11
- package/dist/gates/dependency.d.ts +0 -2
- package/dist/gates/dependency.js +23 -5
- package/dist/gates/deprecated-apis.d.ts +0 -2
- package/dist/gates/deprecated-apis.js +33 -20
- package/dist/gates/duplication-drift/index.d.ts +61 -0
- package/dist/gates/duplication-drift/index.js +240 -0
- package/dist/gates/duplication-drift/similarity.d.ts +68 -0
- package/dist/gates/duplication-drift/similarity.js +177 -0
- package/dist/gates/duplication-drift/tokenizer.d.ts +55 -0
- package/dist/gates/duplication-drift/tokenizer.js +195 -0
- package/dist/gates/frontend-secret-exposure.d.ts +0 -3
- package/dist/gates/frontend-secret-exposure.js +1 -114
- package/dist/gates/frontend-secret-patterns.d.ts +33 -0
- package/dist/gates/frontend-secret-patterns.js +119 -0
- package/dist/gates/{hallucinated-imports.d.ts → hallucinated-imports/index.d.ts} +2 -29
- package/dist/gates/hallucinated-imports/index.js +174 -0
- package/dist/gates/hallucinated-imports/js-resolver.d.ts +45 -0
- package/dist/gates/hallucinated-imports/js-resolver.js +320 -0
- package/dist/gates/hallucinated-imports/manifest-discovery.d.ts +28 -0
- package/dist/gates/hallucinated-imports/manifest-discovery.js +114 -0
- package/dist/gates/hallucinated-imports/python-resolver.d.ts +24 -0
- package/dist/gates/hallucinated-imports/python-resolver.js +306 -0
- package/dist/gates/hallucinated-imports-lang.d.ts +2 -2
- package/dist/gates/hallucinated-imports-lang.js +269 -34
- package/dist/gates/hallucinated-imports.test.js +1 -2
- package/dist/gates/inconsistent-error-handling.d.ts +0 -5
- package/dist/gates/inconsistent-error-handling.js +15 -144
- package/dist/gates/language-adapters/csharp-adapter.d.ts +16 -0
- package/dist/gates/language-adapters/csharp-adapter.js +211 -0
- package/dist/gates/language-adapters/go-adapter.d.ts +26 -0
- package/dist/gates/language-adapters/go-adapter.js +195 -0
- package/dist/gates/language-adapters/index.d.ts +15 -0
- package/dist/gates/language-adapters/index.js +16 -0
- package/dist/gates/language-adapters/java-adapter.d.ts +16 -0
- package/dist/gates/language-adapters/java-adapter.js +237 -0
- package/dist/gates/language-adapters/js-adapter.d.ts +26 -0
- package/dist/gates/language-adapters/js-adapter.js +279 -0
- package/dist/gates/language-adapters/python-adapter.d.ts +25 -0
- package/dist/gates/language-adapters/python-adapter.js +183 -0
- package/dist/gates/language-adapters/registry.d.ts +26 -0
- package/dist/gates/language-adapters/registry.js +65 -0
- package/dist/gates/language-adapters/ruby-adapter.d.ts +25 -0
- package/dist/gates/language-adapters/ruby-adapter.js +217 -0
- package/dist/gates/language-adapters/rust-adapter.d.ts +27 -0
- package/dist/gates/language-adapters/rust-adapter.js +235 -0
- package/dist/gates/language-adapters/types.d.ts +60 -0
- package/dist/gates/language-adapters/types.js +22 -0
- package/dist/gates/logic-drift-extractors.d.ts +15 -0
- package/dist/gates/logic-drift-extractors.js +34 -0
- package/dist/gates/logic-drift.d.ts +0 -30
- package/dist/gates/logic-drift.js +39 -129
- package/dist/gates/phantom-apis.d.ts +0 -2
- package/dist/gates/phantom-apis.js +49 -20
- package/dist/gates/promise-safety.d.ts +0 -1
- package/dist/gates/promise-safety.js +14 -2
- package/dist/gates/runner.js +51 -22
- package/dist/gates/security-patterns-data.d.ts +14 -0
- package/dist/gates/security-patterns-data.js +235 -0
- package/dist/gates/security-patterns.d.ts +17 -3
- package/dist/gates/security-patterns.js +80 -211
- package/dist/gates/side-effect-analysis/categorizer.d.ts +32 -0
- package/dist/gates/side-effect-analysis/categorizer.js +83 -0
- package/dist/gates/{side-effect-analysis.d.ts → side-effect-analysis/index.d.ts} +3 -5
- package/dist/gates/{side-effect-analysis.js → side-effect-analysis/index.js} +33 -45
- package/dist/gates/side-effect-analysis/scope-tracker.d.ts +37 -0
- package/dist/gates/side-effect-analysis/scope-tracker.js +40 -0
- package/dist/gates/side-effect-helpers/index.d.ts +4 -0
- package/dist/gates/side-effect-helpers/index.js +4 -0
- package/dist/gates/side-effect-helpers/pattern-detection.d.ts +123 -0
- package/dist/gates/{side-effect-helpers.js → side-effect-helpers/pattern-detection.js} +22 -468
- package/dist/gates/side-effect-helpers/resource-tracking.d.ts +80 -0
- package/dist/gates/side-effect-helpers/resource-tracking.js +281 -0
- package/dist/gates/side-effect-helpers/scope-analysis.d.ts +21 -0
- package/dist/gates/side-effect-helpers/scope-analysis.js +146 -0
- package/dist/gates/side-effect-helpers/types.d.ts +38 -0
- package/dist/gates/side-effect-helpers/types.js +41 -0
- package/dist/gates/side-effect-rules.d.ts +0 -1
- package/dist/gates/side-effect-rules.js +0 -1
- package/dist/gates/style-drift-rules.d.ts +86 -0
- package/dist/gates/style-drift-rules.js +103 -0
- package/dist/gates/style-drift.d.ts +7 -16
- package/dist/gates/style-drift.js +101 -119
- package/dist/gates/test-quality-matchers.d.ts +53 -0
- package/dist/gates/test-quality-matchers.js +86 -0
- package/dist/gates/test-quality.d.ts +0 -3
- package/dist/gates/test-quality.js +47 -44
- package/dist/hooks/checker.d.ts +0 -1
- package/dist/hooks/checker.js +0 -2
- package/dist/hooks/dlp-templates.d.ts +0 -1
- package/dist/hooks/dlp-templates.js +0 -4
- package/dist/hooks/index.d.ts +0 -2
- package/dist/hooks/index.js +0 -2
- package/dist/hooks/input-validator.d.ts +0 -1
- package/dist/hooks/input-validator.js +0 -1
- package/dist/hooks/input-validator.test.js +0 -1
- package/dist/hooks/standalone-checker.d.ts +0 -1
- package/dist/hooks/standalone-checker.js +0 -1
- package/dist/hooks/standalone-dlp-checker.d.ts +0 -1
- package/dist/hooks/standalone-dlp-checker.js +0 -1
- package/dist/hooks/templates.d.ts +0 -1
- package/dist/hooks/templates.js +0 -1
- package/dist/hooks/types.d.ts +0 -1
- package/dist/hooks/types.js +0 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/services/adaptive-thresholds.d.ts +0 -2
- package/dist/services/adaptive-thresholds.js +0 -2
- package/dist/services/filesystem-cache.d.ts +0 -1
- package/dist/services/filesystem-cache.js +0 -1
- package/dist/services/score-history.d.ts +0 -1
- package/dist/services/score-history.js +0 -1
- package/dist/services/temporal-drift.d.ts +1 -2
- package/dist/services/temporal-drift.js +7 -8
- package/dist/storage/db.d.ts +23 -7
- package/dist/storage/db.js +116 -55
- package/dist/storage/findings.d.ts +4 -3
- package/dist/storage/findings.js +13 -20
- package/dist/storage/local-memory.d.ts +4 -4
- package/dist/storage/local-memory.js +20 -22
- package/dist/storage/patterns.d.ts +5 -5
- package/dist/storage/patterns.js +20 -26
- package/dist/storage/scans.d.ts +6 -6
- package/dist/storage/scans.js +12 -21
- package/dist/types/index.d.ts +1 -0
- package/dist/utils/scanner.js +1 -1
- package/package.json +7 -8
- package/dist/gates/duplication-drift.d.ts +0 -128
- package/dist/gates/duplication-drift.js +0 -585
- package/dist/gates/hallucinated-imports.js +0 -641
- package/dist/gates/side-effect-helpers.d.ts +0 -260
|
@@ -19,9 +19,6 @@
|
|
|
19
19
|
* Go — testing package (t.Run, table-driven tests)
|
|
20
20
|
* Java — JUnit 4/5, TestNG
|
|
21
21
|
* Kotlin — JUnit 5, kotlin.test
|
|
22
|
-
*
|
|
23
|
-
* @since v3.0.0
|
|
24
|
-
* @since v3.0.3 — Go, Java, Kotlin support added
|
|
25
22
|
*/
|
|
26
23
|
import { Gate, GateContext } from './base.js';
|
|
27
24
|
import { Failure, Provenance } from '../types/index.js';
|
|
@@ -19,14 +19,13 @@
|
|
|
19
19
|
* Go — testing package (t.Run, table-driven tests)
|
|
20
20
|
* Java — JUnit 4/5, TestNG
|
|
21
21
|
* Kotlin — JUnit 5, kotlin.test
|
|
22
|
-
*
|
|
23
|
-
* @since v3.0.0
|
|
24
|
-
* @since v3.0.3 — Go, Java, Kotlin support added
|
|
25
22
|
*/
|
|
26
23
|
import { Gate } from './base.js';
|
|
27
24
|
import { FileScanner } from '../utils/scanner.js';
|
|
28
25
|
import { Logger } from '../utils/logger.js';
|
|
26
|
+
import { languageAdapters } from './language-adapters/index.js';
|
|
29
27
|
import { checkGoTestQuality, checkJavaKotlinTestQuality } from './test-quality-lang.js';
|
|
28
|
+
import { JS_TEST_START_PATTERN, JS_ASSERTION_PATTERNS, JS_MOCK_PATTERNS, JS_TAUTOLOGICAL_PATTERNS, JS_VAR_TAUTOLOGY_PATTERN, SNAPSHOT_PATTERNS, PYTHON_TEST_FUNC_PATTERN, PYTHON_ASSERTION_PATTERNS, PYTHON_MOCK_PATTERNS, PYTHON_TAUTOLOGICAL_PATTERNS, PYTHON_FIXTURE_PATTERN, PYTHON_CONFTEST_NAME, } from './test-quality-matchers.js';
|
|
30
29
|
import fs from 'fs-extra';
|
|
31
30
|
import path from 'path';
|
|
32
31
|
export class TestQualityGate extends Gate {
|
|
@@ -51,12 +50,14 @@ export class TestQualityGate extends Gate {
|
|
|
51
50
|
const failures = [];
|
|
52
51
|
const issues = [];
|
|
53
52
|
const defaultPatterns = [
|
|
54
|
-
'**/*.test.{ts,js,tsx,jsx}', '**/*.spec.{ts,js,tsx,jsx}',
|
|
55
|
-
'**/__tests__/**/*.{ts,js,tsx,jsx}',
|
|
53
|
+
'**/*.test.{ts,js,tsx,jsx,mjs,cjs}', '**/*.spec.{ts,js,tsx,jsx,mjs,cjs}',
|
|
54
|
+
'**/__tests__/**/*.{ts,js,tsx,jsx,mjs,cjs}',
|
|
56
55
|
'**/test_*.py', '**/*_test.py', '**/tests/**/*.py',
|
|
57
56
|
'**/*_test.go',
|
|
58
57
|
'**/*Test.java', '**/*Tests.java', '**/src/test/**/*.java',
|
|
59
58
|
'**/*Test.kt', '**/*Tests.kt', '**/src/test/**/*.kt',
|
|
59
|
+
'**/*_test.rs', '**/tests/**/*.rs',
|
|
60
|
+
'**/*_spec.rb', '**/spec/**/*.rb',
|
|
60
61
|
];
|
|
61
62
|
const scanPatterns = context.patterns || defaultPatterns;
|
|
62
63
|
const files = await FileScanner.findFiles({
|
|
@@ -72,27 +73,28 @@ export class TestQualityGate extends Gate {
|
|
|
72
73
|
const fullPath = path.join(context.cwd, file);
|
|
73
74
|
const content = await fs.readFile(fullPath, 'utf-8');
|
|
74
75
|
const ext = path.extname(file);
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
this.
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
76
|
+
const adapter = languageAdapters.getAdapter(file);
|
|
77
|
+
if (!adapter)
|
|
78
|
+
continue;
|
|
79
|
+
const langConfig = {
|
|
80
|
+
check_empty_tests: this.config.check_empty_tests,
|
|
81
|
+
check_tautological: this.config.check_tautological,
|
|
82
|
+
check_mock_heavy: this.config.check_mock_heavy,
|
|
83
|
+
max_mocks_per_test: this.config.max_mocks_per_test,
|
|
84
|
+
};
|
|
85
|
+
switch (adapter.id) {
|
|
86
|
+
case 'js':
|
|
87
|
+
this.checkJSTestQuality(content, file, issues);
|
|
88
|
+
break;
|
|
89
|
+
case 'python':
|
|
90
|
+
this.checkPythonTestQuality(content, file, issues);
|
|
91
|
+
break;
|
|
92
|
+
case 'go':
|
|
93
|
+
checkGoTestQuality(content, file, issues, langConfig);
|
|
94
|
+
break;
|
|
95
|
+
case 'java':
|
|
96
|
+
checkJavaKotlinTestQuality(content, file, ext, issues, langConfig);
|
|
97
|
+
break;
|
|
96
98
|
}
|
|
97
99
|
}
|
|
98
100
|
catch { /* skip */ }
|
|
@@ -125,7 +127,7 @@ export class TestQualityGate extends Gate {
|
|
|
125
127
|
const line = lines[i];
|
|
126
128
|
const trimmed = line.trim();
|
|
127
129
|
// Detect test block start: it('...', () => { or test('...', async () => {
|
|
128
|
-
const testStart = trimmed.match(
|
|
130
|
+
const testStart = trimmed.match(JS_TEST_START_PATTERN);
|
|
129
131
|
if (testStart && !inTestBlock) {
|
|
130
132
|
inTestBlock = true;
|
|
131
133
|
testStartLine = i + 1;
|
|
@@ -159,12 +161,11 @@ export class TestQualityGate extends Gate {
|
|
|
159
161
|
braceDepth--;
|
|
160
162
|
}
|
|
161
163
|
// Check for assertions
|
|
162
|
-
if (
|
|
163
|
-
/\.toEqual|\.toBe|\.toContain|\.toMatch|\.toThrow|\.toHaveBeenCalled|\.toHaveLength|\.toBeTruthy|\.toBeFalsy|\.toBeDefined|\.toBeNull|\.toBeUndefined|\.toBeGreaterThan|\.toBeLessThan|\.toHaveProperty|\.toStrictEqual|\.rejects|\.resolves/.test(line)) {
|
|
164
|
+
if (JS_ASSERTION_PATTERNS.some(p => p.test(line))) {
|
|
164
165
|
hasAssertion = true;
|
|
165
166
|
}
|
|
166
167
|
// Check for mocks
|
|
167
|
-
if (
|
|
168
|
+
if (JS_MOCK_PATTERNS.some(p => p.test(line))) {
|
|
168
169
|
mockCount++;
|
|
169
170
|
}
|
|
170
171
|
// Check for await
|
|
@@ -173,19 +174,24 @@ export class TestQualityGate extends Gate {
|
|
|
173
174
|
}
|
|
174
175
|
// Check for tautological assertions
|
|
175
176
|
if (this.config.check_tautological) {
|
|
176
|
-
if (
|
|
177
|
-
/expect\s*\(\s*false\s*\)\s*\.toBe\s*\(\s*false\s*\)/.test(line) ||
|
|
178
|
-
/expect\s*\(\s*1\s*\)\s*\.toBe\s*\(\s*1\s*\)/.test(line) ||
|
|
179
|
-
/expect\s*\(\s*['"].*['"]\s*\)\s*\.toBe\s*\(\s*['"].*['"]\s*\)/.test(line) && line.match(/expect\s*\(\s*(['"].*?['"])\s*\)\s*\.toBe\s*\(\s*\1\s*\)/)) {
|
|
177
|
+
if (JS_TAUTOLOGICAL_PATTERNS.some(p => p.test(line))) {
|
|
180
178
|
issues.push({
|
|
181
179
|
file, line: i + 1, pattern: 'tautological-assertion',
|
|
182
180
|
reason: 'Tautological assertion — comparing a literal to itself proves nothing',
|
|
183
181
|
});
|
|
184
182
|
}
|
|
183
|
+
// Variable tautology: expect(x).toBe(x), expect(foo).toEqual(foo)
|
|
184
|
+
const varTautology = line.match(JS_VAR_TAUTOLOGY_PATTERN);
|
|
185
|
+
if (varTautology && varTautology[1] === varTautology[2]) {
|
|
186
|
+
issues.push({
|
|
187
|
+
file, line: i + 1, pattern: 'tautological-assertion',
|
|
188
|
+
reason: `Tautological assertion — expect(${varTautology[1]}).toBe(${varTautology[2]}) compares variable to itself`,
|
|
189
|
+
});
|
|
190
|
+
}
|
|
185
191
|
}
|
|
186
192
|
// Check for snapshot-only tests
|
|
187
193
|
if (this.config.check_snapshot_abuse) {
|
|
188
|
-
if (
|
|
194
|
+
if (SNAPSHOT_PATTERNS.some(p => p.test(line))) {
|
|
189
195
|
// This is fine IF there are also semantic assertions
|
|
190
196
|
// We'll check when the block ends
|
|
191
197
|
}
|
|
@@ -240,7 +246,7 @@ export class TestQualityGate extends Gate {
|
|
|
240
246
|
const lines = content.split('\n');
|
|
241
247
|
const basename = path.basename(file);
|
|
242
248
|
// Skip conftest.py entirely — these contain fixtures, not tests
|
|
243
|
-
if (basename ===
|
|
249
|
+
if (basename === PYTHON_CONFTEST_NAME)
|
|
244
250
|
return;
|
|
245
251
|
let inTestFunc = false;
|
|
246
252
|
let testStartLine = 0;
|
|
@@ -253,7 +259,7 @@ export class TestQualityGate extends Gate {
|
|
|
253
259
|
const line = lines[i];
|
|
254
260
|
const trimmed = line.trim();
|
|
255
261
|
// Detect test function start
|
|
256
|
-
const testFuncMatch = line.match(
|
|
262
|
+
const testFuncMatch = line.match(PYTHON_TEST_FUNC_PATTERN);
|
|
257
263
|
if (testFuncMatch) {
|
|
258
264
|
// Check if this function has a @pytest.fixture decorator (not a real test)
|
|
259
265
|
hasFixtureDecorator = false;
|
|
@@ -263,7 +269,7 @@ export class TestQualityGate extends Gate {
|
|
|
263
269
|
continue;
|
|
264
270
|
if (!prevLine.startsWith('@'))
|
|
265
271
|
break;
|
|
266
|
-
if (
|
|
272
|
+
if (PYTHON_FIXTURE_PATTERN.test(prevLine)) {
|
|
267
273
|
hasFixtureDecorator = true;
|
|
268
274
|
break;
|
|
269
275
|
}
|
|
@@ -301,19 +307,16 @@ export class TestQualityGate extends Gate {
|
|
|
301
307
|
}
|
|
302
308
|
testContent += line + '\n';
|
|
303
309
|
// Check for assertions
|
|
304
|
-
if (
|
|
305
|
-
/pytest\.raises\s*\(/.test(trimmed) || /\.assert_called|\.assert_any_call/.test(trimmed)) {
|
|
310
|
+
if (PYTHON_ASSERTION_PATTERNS.some(p => p.test(trimmed))) {
|
|
306
311
|
hasAssertion = true;
|
|
307
312
|
}
|
|
308
313
|
// Check for mocks
|
|
309
|
-
if (
|
|
314
|
+
if (PYTHON_MOCK_PATTERNS.some(p => p.test(trimmed))) {
|
|
310
315
|
mockCount++;
|
|
311
316
|
}
|
|
312
317
|
// Tautological assertions
|
|
313
318
|
if (this.config.check_tautological) {
|
|
314
|
-
if (
|
|
315
|
-
/self\.assertTrue\s*\(\s*True\s*\)/.test(trimmed) ||
|
|
316
|
-
/self\.assertEqual\s*\(\s*(\d+|['"][^'"]*['"])\s*,\s*\1\s*\)/.test(trimmed)) {
|
|
319
|
+
if (PYTHON_TAUTOLOGICAL_PATTERNS.some(p => p.test(trimmed))) {
|
|
317
320
|
issues.push({
|
|
318
321
|
file, line: i + 1, pattern: 'tautological-assertion',
|
|
319
322
|
reason: 'Tautological assertion — comparing a constant to itself proves nothing',
|
package/dist/hooks/checker.d.ts
CHANGED
package/dist/hooks/checker.js
CHANGED
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
*
|
|
7
7
|
* Used by all tool-specific hooks (Claude, Cursor, Cline, Windsurf).
|
|
8
8
|
*
|
|
9
|
-
* @since v3.0.0
|
|
10
9
|
*/
|
|
11
10
|
import fs from 'fs-extra';
|
|
12
11
|
import path from 'path';
|
|
@@ -258,7 +257,6 @@ function simpleGlob(filePath, pattern) {
|
|
|
258
257
|
* enforce_memory: false # allow native memory, still enforce skills
|
|
259
258
|
* enforce_skills: false # allow native skills, still enforce memory
|
|
260
259
|
*
|
|
261
|
-
* @since v4.2.0
|
|
262
260
|
*/
|
|
263
261
|
function checkGovernance(content, relPath, config, failures) {
|
|
264
262
|
const gov = config.gates.governance;
|
|
@@ -11,7 +11,6 @@
|
|
|
11
11
|
* - Cline: PreToolUse executable script
|
|
12
12
|
* - Windsurf: pre_write_code event
|
|
13
13
|
*
|
|
14
|
-
* @since v4.2.0 — AI Agent DLP layer
|
|
15
14
|
*/
|
|
16
15
|
/**
|
|
17
16
|
* Generate DLP (pre-input) hook config files for a specific tool.
|
|
@@ -75,7 +74,6 @@ function generateCursorDLPHooks(checkerCommand) {
|
|
|
75
74
|
* Receives { file_path, new_content } on stdin.
|
|
76
75
|
* Runs Rigour credential scanner on the content.
|
|
77
76
|
*
|
|
78
|
-
* @since v4.2.0 — AI Agent DLP
|
|
79
77
|
*/
|
|
80
78
|
|
|
81
79
|
let data = '';
|
|
@@ -142,7 +140,6 @@ function generateClineDLPHooks(checkerCommand) {
|
|
|
142
140
|
* Receives JSON on stdin with { toolName, toolInput }.
|
|
143
141
|
* Scans tool input for credentials BEFORE execution.
|
|
144
142
|
*
|
|
145
|
-
* @since v4.2.0 — AI Agent DLP
|
|
146
143
|
*/
|
|
147
144
|
|
|
148
145
|
let data = '';
|
|
@@ -225,7 +222,6 @@ function generateWindsurfDLPHooks(checkerCommand) {
|
|
|
225
222
|
* Windsurf DLP hook — scans input for credentials before Cascade agent processing.
|
|
226
223
|
* Receives { file_path, content } on stdin.
|
|
227
224
|
*
|
|
228
|
-
* @since v4.2.0 — AI Agent DLP
|
|
229
225
|
*/
|
|
230
226
|
|
|
231
227
|
let data = '';
|
package/dist/hooks/index.d.ts
CHANGED
package/dist/hooks/index.js
CHANGED
|
@@ -13,7 +13,6 @@
|
|
|
13
13
|
* echo "my api_key = sk-abc123..." | node standalone-dlp-checker.js
|
|
14
14
|
* echo '{"content":"..."}' | node standalone-dlp-checker.js --json
|
|
15
15
|
*
|
|
16
|
-
* @since v4.2.0 — AI Agent DLP
|
|
17
16
|
*/
|
|
18
17
|
import { scanInputForCredentials, formatDLPAlert, createDLPAuditEntry } from './input-validator.js';
|
|
19
18
|
import fs from 'fs-extra';
|
|
@@ -13,7 +13,6 @@
|
|
|
13
13
|
* `rigour hooks check` instead — more portable but requires the CLI binary.
|
|
14
14
|
* Both produce functionally equivalent hook configs for each tool.
|
|
15
15
|
*
|
|
16
|
-
* @since v3.0.0
|
|
17
16
|
*/
|
|
18
17
|
import type { HookTool } from './types.js';
|
|
19
18
|
export interface GeneratedHookFile {
|
package/dist/hooks/templates.js
CHANGED
package/dist/hooks/types.d.ts
CHANGED
package/dist/hooks/types.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ export * from './templates/index.js';
|
|
|
6
6
|
export * from './types/fix-packet.js';
|
|
7
7
|
export { Gate, GateContext } from './gates/base.js';
|
|
8
8
|
export { RetryLoopBreakerGate } from './gates/retry-loop-breaker.js';
|
|
9
|
-
export { SideEffectAnalysisGate } from './gates/side-effect-analysis.js';
|
|
9
|
+
export { SideEffectAnalysisGate } from './gates/side-effect-analysis/index.js';
|
|
10
10
|
export { FrontendSecretExposureGate } from './gates/frontend-secret-exposure.js';
|
|
11
11
|
export * from './utils/logger.js';
|
|
12
12
|
export * from './services/score-history.js';
|
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ export * from './templates/index.js';
|
|
|
6
6
|
export * from './types/fix-packet.js';
|
|
7
7
|
export { Gate } from './gates/base.js';
|
|
8
8
|
export { RetryLoopBreakerGate } from './gates/retry-loop-breaker.js';
|
|
9
|
-
export { SideEffectAnalysisGate } from './gates/side-effect-analysis.js';
|
|
9
|
+
export { SideEffectAnalysisGate } from './gates/side-effect-analysis/index.js';
|
|
10
10
|
export { FrontendSecretExposureGate } from './gates/frontend-secret-exposure.js';
|
|
11
11
|
export * from './utils/logger.js';
|
|
12
12
|
export * from './services/score-history.js';
|
|
@@ -12,8 +12,6 @@
|
|
|
12
12
|
* - Per-provenance failure tracking (AI drift vs structural vs security)
|
|
13
13
|
* - Statistical anomaly detection normalizes across project sizes
|
|
14
14
|
*
|
|
15
|
-
* @since v2.14.0 (original)
|
|
16
|
-
* @since v5.0.0 (Z-score + provenance-aware trends)
|
|
17
15
|
*/
|
|
18
16
|
export type ComplexityTier = 'hobby' | 'startup' | 'enterprise';
|
|
19
17
|
export type QualityTrend = 'improving' | 'stable' | 'degrading';
|
|
@@ -12,8 +12,6 @@
|
|
|
12
12
|
* - Per-provenance failure tracking (AI drift vs structural vs security)
|
|
13
13
|
* - Statistical anomaly detection normalizes across project sizes
|
|
14
14
|
*
|
|
15
|
-
* @since v2.14.0 (original)
|
|
16
|
-
* @since v5.0.0 (Z-score + provenance-aware trends)
|
|
17
15
|
*/
|
|
18
16
|
import * as fs from 'fs';
|
|
19
17
|
import * as path from 'path';
|
|
@@ -15,7 +15,6 @@
|
|
|
15
15
|
* Data source: ~/.rigour/rigour.db (scans + findings tables)
|
|
16
16
|
* All computation is read-only — no writes to DB.
|
|
17
17
|
*
|
|
18
|
-
* @since v5.0.0
|
|
19
18
|
*/
|
|
20
19
|
export type DriftDirection = 'improving' | 'stable' | 'degrading';
|
|
21
20
|
/** A single data point in a time series. */
|
|
@@ -94,7 +93,7 @@ export interface TemporalDriftReport {
|
|
|
94
93
|
* @param cwd - Project root path (used to derive repo name)
|
|
95
94
|
* @param maxScans - Max scans to analyze (default 200)
|
|
96
95
|
*/
|
|
97
|
-
export declare function generateTemporalDriftReport(cwd: string, maxScans?: number): TemporalDriftReport | null
|
|
96
|
+
export declare function generateTemporalDriftReport(cwd: string, maxScans?: number): Promise<TemporalDriftReport | null>;
|
|
98
97
|
/**
|
|
99
98
|
* Get a formatted summary string for CLI/MCP output.
|
|
100
99
|
*/
|
|
@@ -15,7 +15,6 @@
|
|
|
15
15
|
* Data source: ~/.rigour/rigour.db (scans + findings tables)
|
|
16
16
|
* All computation is read-only — no writes to DB.
|
|
17
17
|
*
|
|
18
|
-
* @since v5.0.0
|
|
19
18
|
*/
|
|
20
19
|
import { openDatabase } from '../storage/db.js';
|
|
21
20
|
import { Logger } from '../utils/logger.js';
|
|
@@ -89,8 +88,8 @@ function toWeekKey(timestamp) {
|
|
|
89
88
|
* @param cwd - Project root path (used to derive repo name)
|
|
90
89
|
* @param maxScans - Max scans to analyze (default 200)
|
|
91
90
|
*/
|
|
92
|
-
export function generateTemporalDriftReport(cwd, maxScans = 200) {
|
|
93
|
-
const db = openDatabase();
|
|
91
|
+
export async function generateTemporalDriftReport(cwd, maxScans = 200) {
|
|
92
|
+
const db = await openDatabase();
|
|
94
93
|
if (!db) {
|
|
95
94
|
Logger.warn('Temporal drift: SQLite not available');
|
|
96
95
|
return null;
|
|
@@ -98,20 +97,20 @@ export function generateTemporalDriftReport(cwd, maxScans = 200) {
|
|
|
98
97
|
const repo = path.basename(cwd);
|
|
99
98
|
try {
|
|
100
99
|
// 1. Load all scans (oldest first)
|
|
101
|
-
const scans = db.
|
|
100
|
+
const scans = await db.all(`
|
|
102
101
|
SELECT * FROM scans WHERE repo = ?
|
|
103
102
|
ORDER BY timestamp ASC LIMIT ?
|
|
104
|
-
|
|
103
|
+
`, repo, maxScans);
|
|
105
104
|
if (scans.length < 3) {
|
|
106
105
|
return createEmptyReport(repo, scans.length);
|
|
107
106
|
}
|
|
108
107
|
// 2. Load per-scan provenance failure counts
|
|
109
108
|
const provenanceByScan = new Map();
|
|
110
109
|
for (const scan of scans) {
|
|
111
|
-
const counts = db.
|
|
110
|
+
const counts = await db.all(`
|
|
112
111
|
SELECT provenance, COUNT(*) as cnt FROM findings
|
|
113
112
|
WHERE scan_id = ? GROUP BY provenance
|
|
114
|
-
|
|
113
|
+
`, scan.id);
|
|
115
114
|
const breakdown = { aiDrift: 0, structural: 0, security: 0 };
|
|
116
115
|
for (const row of counts) {
|
|
117
116
|
if (row.provenance === 'ai-drift')
|
|
@@ -233,7 +232,7 @@ export function generateTemporalDriftReport(cwd, maxScans = 200) {
|
|
|
233
232
|
return null;
|
|
234
233
|
}
|
|
235
234
|
finally {
|
|
236
|
-
db.close();
|
|
235
|
+
await db.close();
|
|
237
236
|
}
|
|
238
237
|
}
|
|
239
238
|
// ─── Helpers ────────────────────────────────────────────────────────
|
package/dist/storage/db.d.ts
CHANGED
|
@@ -1,19 +1,35 @@
|
|
|
1
1
|
declare const RIGOUR_DIR: string;
|
|
2
2
|
declare const DB_PATH: string;
|
|
3
|
+
/**
|
|
4
|
+
* Promisified wrapper around a node-sqlite3 Database instance.
|
|
5
|
+
* Provides run/get/all/exec methods that return Promises.
|
|
6
|
+
*/
|
|
3
7
|
export interface RigourDB {
|
|
4
|
-
|
|
5
|
-
|
|
8
|
+
/** Execute a write statement (INSERT/UPDATE/DELETE). Returns { changes }. */
|
|
9
|
+
run(sql: string, ...params: any[]): Promise<{
|
|
10
|
+
changes: number;
|
|
11
|
+
lastID: number;
|
|
12
|
+
}>;
|
|
13
|
+
/** Fetch a single row. */
|
|
14
|
+
get(sql: string, ...params: any[]): Promise<any>;
|
|
15
|
+
/** Fetch all rows. */
|
|
16
|
+
all(sql: string, ...params: any[]): Promise<any[]>;
|
|
17
|
+
/** Execute raw SQL (multi-statement OK). */
|
|
18
|
+
exec(sql: string): Promise<void>;
|
|
19
|
+
/** Close the database connection. */
|
|
20
|
+
close(): Promise<void>;
|
|
21
|
+
/** Run multiple operations atomically via BEGIN/COMMIT/ROLLBACK. */
|
|
22
|
+
transaction<T>(fn: (db: RigourDB) => Promise<T>): Promise<T>;
|
|
6
23
|
}
|
|
7
24
|
/**
|
|
8
25
|
* Open (or create) the Rigour SQLite database.
|
|
9
|
-
* Returns null if
|
|
26
|
+
* Returns null if sqlite3 is not available.
|
|
10
27
|
*/
|
|
11
|
-
export declare function openDatabase(dbPath?: string): RigourDB | null
|
|
28
|
+
export declare function openDatabase(dbPath?: string): Promise<RigourDB | null>;
|
|
12
29
|
/**
|
|
13
30
|
* Compact the database — prune old data, reclaim disk space.
|
|
14
|
-
* Retention policy: keep last `retainDays` of findings, merge old patterns.
|
|
15
31
|
*/
|
|
16
|
-
export declare function compactDatabase(retainDays?: number): CompactResult
|
|
32
|
+
export declare function compactDatabase(retainDays?: number): Promise<CompactResult>;
|
|
17
33
|
export interface CompactResult {
|
|
18
34
|
pruned: number;
|
|
19
35
|
patternsDecayed: number;
|
|
@@ -29,7 +45,7 @@ export declare function getDatabaseSize(): number;
|
|
|
29
45
|
*/
|
|
30
46
|
export declare function resetDatabase(): void;
|
|
31
47
|
/**
|
|
32
|
-
* Check if SQLite is available (
|
|
48
|
+
* Check if SQLite is available (sqlite3 installed)
|
|
33
49
|
*/
|
|
34
50
|
export declare function isSQLiteAvailable(): boolean;
|
|
35
51
|
export { RIGOUR_DIR, DB_PATH };
|