@ryuenn3123/agentic-senior-core 6.5.0 → 6.5.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/.agents/plugins/agentic-senior-core/.codex-plugin/plugin.json +1 -1
- package/.agents/plugins/agentic-senior-core/hooks/dedup-gate.js +83 -5
- package/.agents/plugins/agentic-senior-core/plugin.json +1 -1
- package/.asc/dedup-config.json +6 -2
- package/gemini-extension.json +1 -1
- package/package.json +1 -1
- package/plugin.yaml +1 -1
|
@@ -20,6 +20,63 @@ const JSCPD_TIMEOUT_MS = 10000;
|
|
|
20
20
|
// Recognized source root directories — scan scope walks up to the first match
|
|
21
21
|
const SOURCE_ROOTS = ['src', 'lib', 'app'];
|
|
22
22
|
|
|
23
|
+
// Framework-conventional filenames that MUST be identical across directories by design.
|
|
24
|
+
// Matches where both files share one of these basenames in different dirs are not duplication.
|
|
25
|
+
const FRAMEWORK_CONVENTIONAL_BASENAMES = new Set([
|
|
26
|
+
// Next.js App Router
|
|
27
|
+
'page.tsx', 'page.jsx', 'page.ts', 'page.js',
|
|
28
|
+
'layout.tsx', 'layout.jsx', 'layout.ts', 'layout.js',
|
|
29
|
+
'loading.tsx', 'loading.jsx', 'loading.ts', 'loading.js',
|
|
30
|
+
'error.tsx', 'error.jsx', 'error.ts', 'error.js',
|
|
31
|
+
'not-found.tsx', 'not-found.jsx', 'not-found.ts', 'not-found.js',
|
|
32
|
+
'template.tsx', 'template.jsx', 'template.ts', 'template.js',
|
|
33
|
+
'route.tsx', 'route.ts', 'route.js',
|
|
34
|
+
'default.tsx', 'default.jsx', 'default.ts', 'default.js',
|
|
35
|
+
// Remix
|
|
36
|
+
'root.tsx', 'root.jsx', 'root.ts', 'root.js',
|
|
37
|
+
'entry.server.tsx', 'entry.server.ts', 'entry.client.tsx', 'entry.client.ts',
|
|
38
|
+
// Expo Router
|
|
39
|
+
'_layout.tsx', '_layout.jsx', '_layout.ts', '_layout.js',
|
|
40
|
+
// Nuxt
|
|
41
|
+
'index.vue', 'app.vue',
|
|
42
|
+
// SvelteKit
|
|
43
|
+
'+page.svelte', '+layout.svelte', '+page.server.ts', '+page.server.js',
|
|
44
|
+
'+error.svelte', '+layout.server.ts', '+layout.server.js',
|
|
45
|
+
// Common convention / barrel files
|
|
46
|
+
'index.ts', 'index.js', 'index.tsx', 'index.jsx',
|
|
47
|
+
'types.ts', 'types.d.ts',
|
|
48
|
+
// Config files (declarative, structurally similar across projects)
|
|
49
|
+
'tailwind.config.ts', 'tailwind.config.js', 'tailwind.config.mjs',
|
|
50
|
+
'postcss.config.js', 'postcss.config.mjs', 'postcss.config.cjs',
|
|
51
|
+
'next.config.ts', 'next.config.js', 'next.config.mjs',
|
|
52
|
+
'vite.config.ts', 'vite.config.js', 'vite.config.mjs',
|
|
53
|
+
'tsconfig.json', 'jest.config.ts', 'jest.config.js', 'vitest.config.ts',
|
|
54
|
+
]);
|
|
55
|
+
|
|
56
|
+
// Suffix patterns for frameworks that mandate a naming convention (e.g. Angular).
|
|
57
|
+
// Files matching the same suffix in different dirs are structural, not copy-paste.
|
|
58
|
+
const FRAMEWORK_CONVENTIONAL_SUFFIXES = [
|
|
59
|
+
// Angular (*.component.ts, *.module.ts, *.service.ts, *.pipe.ts, *.directive.ts)
|
|
60
|
+
'.component.ts', '.component.js', '.module.ts', '.service.ts',
|
|
61
|
+
'.pipe.ts', '.directive.ts', '.guard.ts', '.resolver.ts',
|
|
62
|
+
// Storybook
|
|
63
|
+
'.stories.tsx', '.stories.jsx', '.stories.ts', '.stories.js',
|
|
64
|
+
// Test / spec (structurally similar boilerplate across suites)
|
|
65
|
+
'.spec.ts', '.spec.tsx', '.spec.js', '.spec.jsx',
|
|
66
|
+
'.test.ts', '.test.tsx', '.test.js', '.test.jsx',
|
|
67
|
+
];
|
|
68
|
+
|
|
69
|
+
function hasConventionalSuffix(basename) {
|
|
70
|
+
for (var i = 0; i < FRAMEWORK_CONVENTIONAL_SUFFIXES.length; i++) {
|
|
71
|
+
if (basename.endsWith(FRAMEWORK_CONVENTIONAL_SUFFIXES[i])) return true;
|
|
72
|
+
}
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function isFrameworkConventional(basename) {
|
|
77
|
+
return FRAMEWORK_CONVENTIONAL_BASENAMES.has(basename) || hasConventionalSuffix(basename);
|
|
78
|
+
}
|
|
79
|
+
|
|
23
80
|
let inputBuffer = '';
|
|
24
81
|
process.stdin.setEncoding('utf8');
|
|
25
82
|
process.stdin.on('data', chunk => {
|
|
@@ -63,7 +120,7 @@ process.stdin.on('data', chunk => {
|
|
|
63
120
|
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'asc-dedup-'));
|
|
64
121
|
|
|
65
122
|
const ignoreFlags = (config.ignoreDirs || []).map(function (d) { return '--ignore "' + d + '"'; }).join(' ');
|
|
66
|
-
const minTokens = config.minTokens ||
|
|
123
|
+
const minTokens = config.minTokens || 50;
|
|
67
124
|
const scanCmd = ' "' + scanDir + '" --min-tokens ' + minTokens
|
|
68
125
|
+ ' --reporters json --silent --output "' + tmpDir + '" ' + ignoreFlags;
|
|
69
126
|
|
|
@@ -201,7 +258,15 @@ function loadDedupConfig() {
|
|
|
201
258
|
}
|
|
202
259
|
} catch (_) {}
|
|
203
260
|
}
|
|
204
|
-
return {
|
|
261
|
+
return {
|
|
262
|
+
mode: 'advisory',
|
|
263
|
+
minTokens: 50,
|
|
264
|
+
ignoreDirs: [
|
|
265
|
+
'tests', 'test', '__tests__', 'migrations', 'generated', 'node_modules',
|
|
266
|
+
'dist', 'build', '.next', '.nuxt', '.expo', 'coverage', '.storybook',
|
|
267
|
+
'prisma/migrations', 'android', 'ios',
|
|
268
|
+
],
|
|
269
|
+
};
|
|
205
270
|
}
|
|
206
271
|
|
|
207
272
|
// minimal: attempt-then-fallback — try scan directly, fall back on failure.
|
|
@@ -238,6 +303,7 @@ function checkForDuplicates(report, filePath) {
|
|
|
238
303
|
if (duplicates.length === 0) return null;
|
|
239
304
|
|
|
240
305
|
var normalizedTarget = path.resolve(filePath).replace(/\\/g, '/').toLowerCase();
|
|
306
|
+
var targetBasename = path.basename(filePath);
|
|
241
307
|
|
|
242
308
|
for (var i = 0; i < duplicates.length; i++) {
|
|
243
309
|
var dup = duplicates[i];
|
|
@@ -245,9 +311,21 @@ function checkForDuplicates(report, filePath) {
|
|
|
245
311
|
var secondName = path.resolve(dup.secondFile.name).replace(/\\/g, '/').toLowerCase();
|
|
246
312
|
|
|
247
313
|
if (firstName === normalizedTarget || secondName === normalizedTarget) {
|
|
248
|
-
var
|
|
249
|
-
|
|
250
|
-
|
|
314
|
+
var otherRaw = firstName === normalizedTarget ? dup.secondFile.name : dup.firstFile.name;
|
|
315
|
+
var otherBasename = path.basename(otherRaw);
|
|
316
|
+
|
|
317
|
+
// Skip framework-conventional filenames in different directories — identical names
|
|
318
|
+
// are mandated by the framework (e.g. Next.js page.tsx, Angular *.component.ts),
|
|
319
|
+
// not copy-paste duplication.
|
|
320
|
+
if (isFrameworkConventional(targetBasename)
|
|
321
|
+
&& isFrameworkConventional(otherBasename)
|
|
322
|
+
&& path.dirname(path.resolve(filePath)) !== path.dirname(path.resolve(otherRaw))) {
|
|
323
|
+
continue;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// Show relative path instead of bare basename so the developer knows WHICH file.
|
|
327
|
+
var cwd = process.cwd();
|
|
328
|
+
var matchedFile = path.relative(cwd, path.resolve(otherRaw)).replace(/\\/g, '/');
|
|
251
329
|
var lines = dup.lines || 0;
|
|
252
330
|
// jscpd v5 reports fragments; estimate overlap percentage from line count
|
|
253
331
|
var totalLines = (report.statistics && report.statistics.total && report.statistics.total.lines) || 1;
|
package/.asc/dedup-config.json
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"mode": "advisory",
|
|
3
|
-
"minTokens":
|
|
3
|
+
"minTokens": 50,
|
|
4
4
|
"scanRoot": null,
|
|
5
|
-
"ignoreDirs": [
|
|
5
|
+
"ignoreDirs": [
|
|
6
|
+
"tests", "test", "__tests__", "migrations", "generated", "node_modules",
|
|
7
|
+
"dist", "build", ".next", ".nuxt", ".expo", "coverage", ".storybook",
|
|
8
|
+
"prisma/migrations", "android", "ios"
|
|
9
|
+
]
|
|
6
10
|
}
|
package/gemini-extension.json
CHANGED
package/package.json
CHANGED
package/plugin.yaml
CHANGED