@ryuenn3123/agentic-senior-core 6.5.1 → 6.5.2
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/.agents/plugins/agentic-senior-core/.codex-plugin/plugin.json +1 -1
- package/.agents/plugins/agentic-senior-core/hooks/dedup-gate.js +15 -5
- package/.agents/plugins/agentic-senior-core/plugin.json +1 -1
- package/.asc/dedup-config.json +1 -1
- package/gemini-extension.json +1 -1
- package/lib/cli/commands/git-hook-generator.mjs +85 -6
- package/package.json +1 -1
- package/plugin.yaml +1 -1
|
@@ -120,7 +120,7 @@ process.stdin.on('data', chunk => {
|
|
|
120
120
|
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'asc-dedup-'));
|
|
121
121
|
|
|
122
122
|
const ignoreFlags = (config.ignoreDirs || []).map(function (d) { return '--ignore "' + d + '"'; }).join(' ');
|
|
123
|
-
const minTokens = config.minTokens ||
|
|
123
|
+
const minTokens = config.minTokens || 30;
|
|
124
124
|
const scanCmd = ' "' + scanDir + '" --min-tokens ' + minTokens
|
|
125
125
|
+ ' --reporters json --silent --output "' + tmpDir + '" ' + ignoreFlags;
|
|
126
126
|
|
|
@@ -260,7 +260,7 @@ function loadDedupConfig() {
|
|
|
260
260
|
}
|
|
261
261
|
return {
|
|
262
262
|
mode: 'advisory',
|
|
263
|
-
minTokens:
|
|
263
|
+
minTokens: 30,
|
|
264
264
|
ignoreDirs: [
|
|
265
265
|
'tests', 'test', '__tests__', 'migrations', 'generated', 'node_modules',
|
|
266
266
|
'dist', 'build', '.next', '.nuxt', '.expo', 'coverage', '.storybook',
|
|
@@ -327,9 +327,19 @@ function checkForDuplicates(report, filePath) {
|
|
|
327
327
|
var cwd = process.cwd();
|
|
328
328
|
var matchedFile = path.relative(cwd, path.resolve(otherRaw)).replace(/\\/g, '/');
|
|
329
329
|
var lines = dup.lines || 0;
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
330
|
+
var totalFileLines = 1;
|
|
331
|
+
try {
|
|
332
|
+
totalFileLines = fs.readFileSync(path.resolve(filePath), 'utf8').split('\n').length || 1;
|
|
333
|
+
} catch (_) {
|
|
334
|
+
totalFileLines = dup.firstFile.lines || dup.secondFile.lines || lines || 1;
|
|
335
|
+
}
|
|
336
|
+
var percent = Math.round((lines / totalFileLines) * 100);
|
|
337
|
+
|
|
338
|
+
// Skip trivial matches (import boilerplate, small overlaps)
|
|
339
|
+
if (lines < 10 && percent < 10) {
|
|
340
|
+
continue;
|
|
341
|
+
}
|
|
342
|
+
|
|
333
343
|
return { matchedFile: matchedFile, lines: lines, percent: percent };
|
|
334
344
|
}
|
|
335
345
|
}
|
package/.asc/dedup-config.json
CHANGED
package/gemini-extension.json
CHANGED
|
@@ -27,6 +27,51 @@ const SOURCE_EXTENSIONS = new Set([${extensionsList}]);
|
|
|
27
27
|
|
|
28
28
|
const JSCPD_TIMEOUT_MS = 10000;
|
|
29
29
|
|
|
30
|
+
// Framework-conventional filenames that MUST be identical across directories by design.
|
|
31
|
+
const FRAMEWORK_CONVENTIONAL_BASENAMES = new Set([
|
|
32
|
+
'page.tsx', 'page.jsx', 'page.ts', 'page.js',
|
|
33
|
+
'layout.tsx', 'layout.jsx', 'layout.ts', 'layout.js',
|
|
34
|
+
'loading.tsx', 'loading.jsx', 'loading.ts', 'loading.js',
|
|
35
|
+
'error.tsx', 'error.jsx', 'error.ts', 'error.js',
|
|
36
|
+
'not-found.tsx', 'not-found.jsx', 'not-found.ts', 'not-found.js',
|
|
37
|
+
'template.tsx', 'template.jsx', 'template.ts', 'template.js',
|
|
38
|
+
'route.tsx', 'route.ts', 'route.js',
|
|
39
|
+
'default.tsx', 'default.jsx', 'default.ts', 'default.js',
|
|
40
|
+
'root.tsx', 'root.jsx', 'root.ts', 'root.js',
|
|
41
|
+
'entry.server.tsx', 'entry.server.ts', 'entry.client.tsx', 'entry.client.ts',
|
|
42
|
+
'_layout.tsx', '_layout.jsx', '_layout.ts', '_layout.js',
|
|
43
|
+
'index.vue', 'app.vue',
|
|
44
|
+
'+page.svelte', '+layout.svelte', '+page.server.ts', '+page.server.js',
|
|
45
|
+
'+error.svelte', '+layout.server.ts', '+layout.server.js',
|
|
46
|
+
'index.ts', 'index.js', 'index.tsx', 'index.jsx',
|
|
47
|
+
'types.ts', 'types.d.ts',
|
|
48
|
+
'tailwind.config.ts', 'tailwind.config.js', 'tailwind.config.mjs',
|
|
49
|
+
'postcss.config.js', 'postcss.config.mjs', 'postcss.config.cjs',
|
|
50
|
+
'next.config.ts', 'next.config.js', 'next.config.mjs',
|
|
51
|
+
'vite.config.ts', 'vite.config.js', 'vite.config.mjs',
|
|
52
|
+
'tsconfig.json', 'jest.config.ts', 'jest.config.js', 'vitest.config.ts',
|
|
53
|
+
]);
|
|
54
|
+
|
|
55
|
+
const FRAMEWORK_CONVENTIONAL_SUFFIXES = [
|
|
56
|
+
'.component.ts', '.component.js', '.module.ts', '.service.ts',
|
|
57
|
+
'.pipe.ts', '.directive.ts', '.guard.ts', '.resolver.ts',
|
|
58
|
+
'.stories.tsx', '.stories.jsx', '.stories.ts', '.stories.js',
|
|
59
|
+
'.spec.ts', '.spec.tsx', '.spec.js', '.spec.jsx',
|
|
60
|
+
'.test.ts', '.test.tsx', '.test.js', '.test.jsx',
|
|
61
|
+
];
|
|
62
|
+
|
|
63
|
+
function isFrameworkConventional(basename) {
|
|
64
|
+
if (FRAMEWORK_CONVENTIONAL_BASENAMES.has(basename)) return true;
|
|
65
|
+
for (var i = 0; i < FRAMEWORK_CONVENTIONAL_SUFFIXES.length; i++) {
|
|
66
|
+
if (basename.endsWith(FRAMEWORK_CONVENTIONAL_SUFFIXES[i])) return true;
|
|
67
|
+
}
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Minimum thresholds — skip trivial matches (import boilerplate, etc.)
|
|
72
|
+
const MIN_LINES_THRESHOLD = 10;
|
|
73
|
+
const MIN_PERCENT_THRESHOLD = 10;
|
|
74
|
+
|
|
30
75
|
function getStagedFiles(cwd) {
|
|
31
76
|
try {
|
|
32
77
|
const output = execSync('git diff --cached --name-only --diff-filter=ACM', { encoding: 'utf8', cwd });
|
|
@@ -48,7 +93,14 @@ function loadDedupConfig(cwd) {
|
|
|
48
93
|
}
|
|
49
94
|
} catch (_) {}
|
|
50
95
|
}
|
|
51
|
-
return {
|
|
96
|
+
return {
|
|
97
|
+
minTokens: 30,
|
|
98
|
+
ignoreDirs: [
|
|
99
|
+
'tests', 'test', '__tests__', 'migrations', 'generated', 'node_modules',
|
|
100
|
+
'dist', 'build', '.next', '.nuxt', '.expo', 'coverage', '.storybook',
|
|
101
|
+
'prisma/migrations', 'android', 'ios',
|
|
102
|
+
],
|
|
103
|
+
};
|
|
52
104
|
}
|
|
53
105
|
|
|
54
106
|
function runEslintAutoFix(cwd, stagedFiles) {
|
|
@@ -126,10 +178,34 @@ function checkForDuplicates(report, stagedSourceFiles, cwd) {
|
|
|
126
178
|
|
|
127
179
|
if (isFirstStaged || isSecondStaged) {
|
|
128
180
|
const stagedFile = isFirstStaged ? normalizedStagedMap.get(firstName) : normalizedStagedMap.get(secondName);
|
|
129
|
-
const
|
|
181
|
+
const otherRaw = isFirstStaged ? dup.secondFile.name : dup.firstFile.name;
|
|
182
|
+
const otherBasename = path.basename(otherRaw);
|
|
183
|
+
const stagedBasename = path.basename(stagedFile);
|
|
184
|
+
|
|
185
|
+
// Skip framework-conventional filenames in different directories
|
|
186
|
+
if (isFrameworkConventional(stagedBasename)
|
|
187
|
+
&& isFrameworkConventional(otherBasename)
|
|
188
|
+
&& path.dirname(path.resolve(cwd, stagedFile)) !== path.dirname(path.resolve(cwd, otherRaw))) {
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
|
|
130
192
|
const lines = dup.lines || 0;
|
|
131
|
-
|
|
132
|
-
|
|
193
|
+
// Calculate percent relative to the actual staged file size
|
|
194
|
+
let totalFileLines = 1;
|
|
195
|
+
try {
|
|
196
|
+
totalFileLines = fs.readFileSync(path.resolve(cwd, stagedFile), 'utf8').split('\\n').length || 1;
|
|
197
|
+
} catch (_) {
|
|
198
|
+
totalFileLines = dup.firstFile.lines || dup.secondFile.lines || lines || 1;
|
|
199
|
+
}
|
|
200
|
+
const percent = Math.round((lines / totalFileLines) * 100);
|
|
201
|
+
|
|
202
|
+
// Skip trivial matches (import boilerplate, small overlaps)
|
|
203
|
+
if (lines < MIN_LINES_THRESHOLD && percent < MIN_PERCENT_THRESHOLD) {
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// Show relative path for actionable messages
|
|
208
|
+
const matchedFile = path.relative(cwd, path.resolve(cwd, otherRaw)).replace(/\\\\/g, '/');
|
|
133
209
|
return { stagedFile, matchedFile, lines, percent };
|
|
134
210
|
}
|
|
135
211
|
}
|
|
@@ -185,8 +261,11 @@ function runPreCommitGate() {
|
|
|
185
261
|
})));
|
|
186
262
|
|
|
187
263
|
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'asc-git-dedup-'));
|
|
188
|
-
const ignoreFlags = (config.ignoreDirs || [
|
|
189
|
-
|
|
264
|
+
const ignoreFlags = (config.ignoreDirs || [
|
|
265
|
+
'tests', 'test', '__tests__', 'migrations', 'generated', 'node_modules',
|
|
266
|
+
'dist', 'build', '.next', '.nuxt', '.expo', 'coverage', '.storybook',
|
|
267
|
+
'prisma/migrations', 'android', 'ios',
|
|
268
|
+
]).map(d => \`--ignore "\${d}"\`).join(' ');
|
|
190
269
|
const minTokens = config.minTokens || 30;
|
|
191
270
|
|
|
192
271
|
let finding = null;
|
package/package.json
CHANGED
package/plugin.yaml
CHANGED