ai-warden 0.2.1 → 0.3.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/package.json +1 -1
- package/src/cli.js +15 -1
- package/src/fileClassifier.js +146 -0
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
const fs = require('fs');
|
|
9
9
|
const path = require('path');
|
|
10
10
|
const scanner = require('./scanner');
|
|
11
|
+
const fileClassifier = require('./fileClassifier');
|
|
11
12
|
|
|
12
13
|
const args = process.argv.slice(2);
|
|
13
14
|
const command = args[0];
|
|
@@ -82,10 +83,23 @@ function scanCommand(targetPath, options = {}) {
|
|
|
82
83
|
|
|
83
84
|
files.forEach(file => {
|
|
84
85
|
try {
|
|
86
|
+
// Check if file should be skipped
|
|
87
|
+
if (fileClassifier.shouldSkipFile(file)) {
|
|
88
|
+
if (options.verbose) {
|
|
89
|
+
console.log(`⏭️ ${path.relative(process.cwd(), file)} - Skipped`);
|
|
90
|
+
}
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
85
94
|
const content = fs.readFileSync(file, 'utf-8');
|
|
95
|
+
const fileType = fileClassifier.classifyFile(file);
|
|
96
|
+
const baseThreshold = options.mode === 'strict' ? 75 : options.mode === 'permissive' ? 250 : 150;
|
|
97
|
+
const adjustedThreshold = fileClassifier.getAdjustedThreshold(fileType, baseThreshold);
|
|
98
|
+
|
|
86
99
|
const result = scanner.scan(content, {
|
|
87
100
|
mode: options.mode || 'balanced',
|
|
88
|
-
|
|
101
|
+
threshold: adjustedThreshold,
|
|
102
|
+
context: fileClassifier.getFileContext(file),
|
|
89
103
|
verbose: options.verbose
|
|
90
104
|
});
|
|
91
105
|
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File Classifier
|
|
3
|
+
* Determines if a file should be scanned differently based on its type/purpose
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const path = require('path');
|
|
7
|
+
|
|
8
|
+
// Files that should be completely skipped
|
|
9
|
+
const SKIP_PATTERNS = [
|
|
10
|
+
/node_modules/,
|
|
11
|
+
/\.git/,
|
|
12
|
+
/\.vscode/,
|
|
13
|
+
/\.idea/,
|
|
14
|
+
/dist\//,
|
|
15
|
+
/build\//,
|
|
16
|
+
/coverage\//,
|
|
17
|
+
/\.min\.js$/,
|
|
18
|
+
/\.bundle\.js$/,
|
|
19
|
+
/package-lock\.json$/,
|
|
20
|
+
/yarn\.lock$/
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
// Documentation files (lower threshold, whitelist common patterns)
|
|
24
|
+
const DOCUMENTATION_PATTERNS = [
|
|
25
|
+
/\.md$/,
|
|
26
|
+
/\.txt$/,
|
|
27
|
+
/README/i,
|
|
28
|
+
/CHANGELOG/i,
|
|
29
|
+
/LICENSE/i,
|
|
30
|
+
/CONTRIBUTING/i,
|
|
31
|
+
/docs?\//i,
|
|
32
|
+
/examples?\//i
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
// Test files (lower threshold)
|
|
36
|
+
const TEST_PATTERNS = [
|
|
37
|
+
/\.test\.(js|ts|jsx|tsx|py|java)$/,
|
|
38
|
+
/\.spec\.(js|ts|jsx|tsx|py|java)$/,
|
|
39
|
+
/__tests__\//,
|
|
40
|
+
/tests?\//,
|
|
41
|
+
/test\//,
|
|
42
|
+
/spec\//,
|
|
43
|
+
/\.test$/,
|
|
44
|
+
/\.spec$/
|
|
45
|
+
];
|
|
46
|
+
|
|
47
|
+
// API specification files (very permissive, lots of example data)
|
|
48
|
+
const API_SPEC_PATTERNS = [
|
|
49
|
+
/swagger\.(yaml|yml|json)$/,
|
|
50
|
+
/openapi\.(yaml|yml|json)$/,
|
|
51
|
+
/api-spec/i,
|
|
52
|
+
/postman/i
|
|
53
|
+
];
|
|
54
|
+
|
|
55
|
+
// Configuration files (usually safe)
|
|
56
|
+
const CONFIG_PATTERNS = [
|
|
57
|
+
/\.(json|yaml|yml|toml|ini|conf)$/,
|
|
58
|
+
/\.config\.(js|ts)$/,
|
|
59
|
+
/\.rc$/
|
|
60
|
+
];
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Classify a file based on its path
|
|
64
|
+
* Returns: 'skip' | 'documentation' | 'test' | 'api-spec' | 'config' | 'code'
|
|
65
|
+
*/
|
|
66
|
+
function classifyFile(filePath) {
|
|
67
|
+
const normalized = path.normalize(filePath);
|
|
68
|
+
|
|
69
|
+
// Check if should be skipped entirely
|
|
70
|
+
if (SKIP_PATTERNS.some(pattern => pattern.test(normalized))) {
|
|
71
|
+
return 'skip';
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Check documentation
|
|
75
|
+
if (DOCUMENTATION_PATTERNS.some(pattern => pattern.test(normalized))) {
|
|
76
|
+
return 'documentation';
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Check test files
|
|
80
|
+
if (TEST_PATTERNS.some(pattern => pattern.test(normalized))) {
|
|
81
|
+
return 'test';
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Check API specs
|
|
85
|
+
if (API_SPEC_PATTERNS.some(pattern => pattern.test(normalized))) {
|
|
86
|
+
return 'api-spec';
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Check config files
|
|
90
|
+
if (CONFIG_PATTERNS.some(pattern => pattern.test(normalized))) {
|
|
91
|
+
return 'config';
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Default: treat as code
|
|
95
|
+
return 'code';
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Get adjusted threshold based on file type
|
|
100
|
+
*/
|
|
101
|
+
function getAdjustedThreshold(fileType, baseThreshold) {
|
|
102
|
+
const multipliers = {
|
|
103
|
+
'skip': 0, // Will be skipped anyway
|
|
104
|
+
'documentation': 4.0, // Very permissive (600 for balanced mode)
|
|
105
|
+
'test': 3.5, // Very permissive (525 for balanced) - test data often triggers patterns
|
|
106
|
+
'api-spec': 5.0, // Extremely permissive (750 for balanced)
|
|
107
|
+
'config': 2.0, // Permissive (300 for balanced)
|
|
108
|
+
'code': 1.0 // Normal threshold
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
return Math.floor(baseThreshold * (multipliers[fileType] || 1.0));
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Should we skip scanning this file entirely?
|
|
116
|
+
*/
|
|
117
|
+
function shouldSkipFile(filePath) {
|
|
118
|
+
return classifyFile(filePath) === 'skip';
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Get context string for better pattern matching
|
|
123
|
+
*/
|
|
124
|
+
function getFileContext(filePath) {
|
|
125
|
+
const fileType = classifyFile(filePath);
|
|
126
|
+
|
|
127
|
+
const contextMap = {
|
|
128
|
+
'documentation': 'documentation',
|
|
129
|
+
'test': 'test',
|
|
130
|
+
'api-spec': 'api-spec',
|
|
131
|
+
'config': 'config',
|
|
132
|
+
'code': 'general'
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
return contextMap[fileType] || 'general';
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
module.exports = {
|
|
139
|
+
classifyFile,
|
|
140
|
+
getAdjustedThreshold,
|
|
141
|
+
shouldSkipFile,
|
|
142
|
+
getFileContext,
|
|
143
|
+
DOCUMENTATION_PATTERNS,
|
|
144
|
+
TEST_PATTERNS,
|
|
145
|
+
API_SPEC_PATTERNS
|
|
146
|
+
};
|