aico-ai 1.1.5 → 1.1.6
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/.aicoignore +41 -6
- package/lib/git-utils.js +8 -6
- package/lib/ignore-utils.js +70 -0
- package/lib/rules-engine.js +5 -1
- package/package.json +1 -1
package/.aicoignore
CHANGED
|
@@ -1,18 +1,53 @@
|
|
|
1
|
-
#
|
|
1
|
+
# .aicoignore — files and patterns excluded from aico review, rules, and security scan
|
|
2
|
+
# Same syntax as .gitignore: glob patterns, one per line, # for comments
|
|
2
3
|
|
|
3
4
|
# Dependencies
|
|
4
|
-
node_modules
|
|
5
|
+
node_modules/**
|
|
5
6
|
package-lock.json
|
|
6
7
|
yarn.lock
|
|
7
8
|
pnpm-lock.yaml
|
|
9
|
+
bun.lockb
|
|
8
10
|
|
|
9
11
|
# Build outputs
|
|
10
|
-
dist
|
|
11
|
-
build
|
|
12
|
+
dist/**
|
|
13
|
+
build/**
|
|
14
|
+
out/**
|
|
15
|
+
.next/**
|
|
16
|
+
.nuxt/**
|
|
12
17
|
|
|
13
|
-
#
|
|
18
|
+
# Environment / secrets
|
|
14
19
|
.env
|
|
15
20
|
.env.*
|
|
16
21
|
|
|
17
|
-
#
|
|
22
|
+
# Test snapshots & coverage
|
|
23
|
+
**/__snapshots__/**
|
|
24
|
+
*.snap
|
|
25
|
+
coverage/**
|
|
26
|
+
.nyc_output/**
|
|
27
|
+
|
|
28
|
+
# Binary / media assets
|
|
29
|
+
*.png
|
|
30
|
+
*.jpg
|
|
31
|
+
*.jpeg
|
|
32
|
+
*.gif
|
|
33
|
+
*.svg
|
|
34
|
+
*.ico
|
|
35
|
+
*.pdf
|
|
36
|
+
*.zip
|
|
37
|
+
*.gz
|
|
38
|
+
*.tar
|
|
39
|
+
*.wasm
|
|
40
|
+
|
|
41
|
+
# Auto-generated / minified
|
|
42
|
+
*.min.js
|
|
43
|
+
*.bundle.js
|
|
44
|
+
*.min.css
|
|
45
|
+
|
|
46
|
+
# Database migrations
|
|
47
|
+
prisma/migrations/**
|
|
48
|
+
|
|
49
|
+
# Logs
|
|
18
50
|
*.log
|
|
51
|
+
|
|
52
|
+
# Vendored / third-party code
|
|
53
|
+
vendor/**
|
package/lib/git-utils.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { simpleGit } from 'simple-git';
|
|
2
2
|
import pc from 'picocolors';
|
|
3
3
|
import fs from 'fs';
|
|
4
|
+
import { loadAicoIgnore, toGitExclude } from './ignore-utils.js';
|
|
4
5
|
|
|
5
6
|
const git = simpleGit();
|
|
6
7
|
|
|
@@ -11,10 +12,10 @@ const IGNORED_FILES = [
|
|
|
11
12
|
'pnpm-lock.yaml',
|
|
12
13
|
'bun.lockb',
|
|
13
14
|
'.env',
|
|
14
|
-
'*.png', '*.jpg', '*.jpeg', '*.gif', '*.svg', '*.ico',
|
|
15
|
-
'*.pdf', '*.zip', '*.gz', '*.tar',
|
|
16
|
-
'dist/*', 'build/*', '.next/*', 'node_modules/*',
|
|
17
|
-
'prisma/migrations/*',
|
|
15
|
+
'*.png', '*.jpg', '*.jpeg', '*.gif', '*.svg', '*.ico',
|
|
16
|
+
'*.pdf', '*.zip', '*.gz', '*.tar',
|
|
17
|
+
'dist/*', 'build/*', '.next/*', 'node_modules/*',
|
|
18
|
+
'prisma/migrations/*',
|
|
18
19
|
];
|
|
19
20
|
|
|
20
21
|
/**
|
|
@@ -23,8 +24,9 @@ const IGNORED_FILES = [
|
|
|
23
24
|
*/
|
|
24
25
|
export async function getStagedDiff() {
|
|
25
26
|
try {
|
|
26
|
-
|
|
27
|
-
const
|
|
27
|
+
const aicoIgnorePatterns = loadAicoIgnore();
|
|
28
|
+
const allIgnored = [...IGNORED_FILES, ...aicoIgnorePatterns];
|
|
29
|
+
const excludeArgs = allIgnored.map(toGitExclude);
|
|
28
30
|
let diff = await git.diff(['--cached', '--', '.', ...excludeArgs]);
|
|
29
31
|
|
|
30
32
|
return diff;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
|
|
4
|
+
const AICOIGNORE_PATH = '.aicoignore';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Reads .aicoignore from the project root and returns an array of patterns.
|
|
8
|
+
* Ignores blank lines and lines starting with #.
|
|
9
|
+
* @returns {string[]}
|
|
10
|
+
*/
|
|
11
|
+
export function loadAicoIgnore() {
|
|
12
|
+
try {
|
|
13
|
+
if (!fs.existsSync(AICOIGNORE_PATH)) return [];
|
|
14
|
+
|
|
15
|
+
return fs.readFileSync(AICOIGNORE_PATH, 'utf-8')
|
|
16
|
+
.split('\n')
|
|
17
|
+
.map(line => line.trim())
|
|
18
|
+
.filter(line => line.length > 0 && !line.startsWith('#'));
|
|
19
|
+
} catch {
|
|
20
|
+
return [];
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Converts a .aicoignore / glob-style pattern to a git pathspec exclude string.
|
|
26
|
+
* @param {string} pattern
|
|
27
|
+
* @returns {string}
|
|
28
|
+
*/
|
|
29
|
+
export function toGitExclude(pattern) {
|
|
30
|
+
return `:(exclude)${pattern}`;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Checks whether a file path matches any of the given .aicoignore-style patterns.
|
|
35
|
+
* Supports * (any segment) and ** (any path).
|
|
36
|
+
* @param {string} filePath
|
|
37
|
+
* @param {string[]} patterns
|
|
38
|
+
* @returns {boolean}
|
|
39
|
+
*/
|
|
40
|
+
export function matchesAicoIgnore(filePath, patterns) {
|
|
41
|
+
const normalized = filePath.replace(/\\/g, '/');
|
|
42
|
+
|
|
43
|
+
for (const pattern of patterns) {
|
|
44
|
+
if (globMatch(normalized, pattern)) return true;
|
|
45
|
+
}
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Minimal glob matcher supporting *, **, and ? wildcards.
|
|
51
|
+
* @param {string} str
|
|
52
|
+
* @param {string} pattern
|
|
53
|
+
* @returns {boolean}
|
|
54
|
+
*/
|
|
55
|
+
function globMatch(str, pattern) {
|
|
56
|
+
const regexStr = pattern
|
|
57
|
+
.replace(/\./g, '\\.')
|
|
58
|
+
.replace(/\*\*/g, '\u0001') // placeholder for **
|
|
59
|
+
.replace(/\*/g, '[^/]*') // * = anything except /
|
|
60
|
+
.replace(/\u0001/g, '.*') // ** = anything including /
|
|
61
|
+
.replace(/\?/g, '[^/]');
|
|
62
|
+
|
|
63
|
+
// Match against the full path or just the basename
|
|
64
|
+
const fullMatch = new RegExp(`^${regexStr}$`).test(str);
|
|
65
|
+
const baseMatch = new RegExp(`^${regexStr}$`).test(path.basename(str));
|
|
66
|
+
// Also match if pattern has no slash and matches basename
|
|
67
|
+
const noSlash = !pattern.includes('/');
|
|
68
|
+
|
|
69
|
+
return fullMatch || (noSlash && baseMatch);
|
|
70
|
+
}
|
package/lib/rules-engine.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import pc from 'picocolors';
|
|
4
|
+
import { loadAicoIgnore, matchesAicoIgnore } from './ignore-utils.js';
|
|
4
5
|
|
|
5
6
|
const RULES_PATH = '.aico/rules.json';
|
|
6
7
|
const DEFAULT_RULES_TEMPLATE = {
|
|
@@ -136,10 +137,13 @@ export function validateAgainstRules(diff, fileContent, filePath) {
|
|
|
136
137
|
|
|
137
138
|
const violations = [];
|
|
138
139
|
|
|
139
|
-
// Check if file should be ignored
|
|
140
|
+
// Check if file should be ignored (rules.json ignore list or .aicoignore)
|
|
140
141
|
if (shouldIgnoreFile(filePath, rules.ignore)) {
|
|
141
142
|
return [];
|
|
142
143
|
}
|
|
144
|
+
if (matchesAicoIgnore(filePath, loadAicoIgnore())) {
|
|
145
|
+
return [];
|
|
146
|
+
}
|
|
143
147
|
|
|
144
148
|
// Check forbidden patterns
|
|
145
149
|
if (rules.rules.forbidden) {
|