@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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentic-senior-core",
3
- "version": "6.5.0",
3
+ "version": "6.5.1",
4
4
  "description": "Universal AI coding rules. Write code like a staff engineer.",
5
5
  "skills": "./skills/",
6
6
  "hooks": "./hooks/hooks.json",
@@ -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 || 30;
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 { mode: 'advisory', minTokens: 30, ignoreDirs: ['tests', 'migrations', 'generated', 'node_modules'] };
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 matchedFile = firstName === normalizedTarget
249
- ? path.basename(dup.secondFile.name)
250
- : path.basename(dup.firstFile.name);
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;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentic-senior-core",
3
- "version": "6.5.0",
3
+ "version": "6.5.1",
4
4
  "description": "Universal AI coding rules. Because your AI writes code like it gets paid by the line.",
5
5
  "contextFileName": "rules/agentic-senior-core.md",
6
6
  "rules": [
@@ -1,6 +1,10 @@
1
1
  {
2
2
  "mode": "advisory",
3
- "minTokens": 30,
3
+ "minTokens": 50,
4
4
  "scanRoot": null,
5
- "ignoreDirs": ["tests", "migrations", "generated", "node_modules"]
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
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentic-senior-core",
3
- "version": "6.5.0",
3
+ "version": "6.5.1",
4
4
  "description": "Universal AI coding rules. Write code like a staff engineer.",
5
5
  "author": "fatidaprilian",
6
6
  "license": "MIT",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ryuenn3123/agentic-senior-core",
3
- "version": "6.5.0",
3
+ "version": "6.5.1",
4
4
  "type": "module",
5
5
  "description": "Agentic Senior Core: Universal AI coding rules and workflows. Write code like a staff engineer, not a junior.",
6
6
  "bin": {
package/plugin.yaml CHANGED
@@ -1,5 +1,5 @@
1
1
  name: agentic-senior-core
2
- version: 6.5.0
2
+ version: 6.5.1
3
3
  description: Universal AI coding rules. Write code like a staff engineer.
4
4
  author: fatidaprilian
5
5
  provides_hooks: