@nebutra/next-unicorn-skill 1.0.6 → 1.0.8

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/SKILL.md CHANGED
@@ -2,10 +2,12 @@
2
2
  name: analyze-and-recommend-third-party-optimizations
3
3
  description: >-
4
4
  Scan a codebase to identify hand-rolled implementations that should be replaced
5
- by third-party libraries, and identify missing capabilities the project should
6
- have. Produce structured migration plans with Context7-verified recommendations.
5
+ by third-party libraries, identify missing capabilities, and detect code
6
+ organization issues (directory structure, naming, circular deps, barrel bloat).
7
+ Produce structured migration plans with Context7-verified recommendations.
7
8
  Use when analyzing technical debt, auditing dependency health, reviewing
8
- hand-rolled code, planning library migrations, or assessing capability gaps.
9
+ hand-rolled code, planning library migrations, assessing capability gaps,
10
+ or auditing project structure and module organization.
9
11
  ---
10
12
 
11
13
  # Analyze and Recommend Third-Party Optimizations
@@ -13,15 +15,27 @@ description: >-
13
15
  ## Architecture
14
16
 
15
17
  ```
16
- Scanner (deterministic) → AI Agent (generative) → Pipeline (deterministic)
17
- Regex patterns detect 1. Recommend replacements Score, plan, audit,
18
- hand-rolled code 2. Identify capability gaps filter, serialize
19
- using knowledge + Context7
18
+ Scanner (deterministic) → AI Agent (generative) → Pipeline (deterministic)
19
+ 1. Regex: detect hand-rolled code 1. Recommend library replacements Score, plan, audit,
20
+ 2. FS: detect code org issues 2. Identify capability gaps filter, serialize
21
+ (god-dirs, circular deps, 3. Recommend org patterns + tooling
22
+ naming, barrel bloat) using knowledge + Context7
20
23
  ```
21
24
 
22
25
  **Design constraints**:
23
26
  - No hardcoded library recommendations — evaluate project context dynamically
24
27
  - Two analysis modes: **replacement** (hand-rolled code found) and **gap** (capability missing entirely)
28
+ - **Human-in-the-loop**: 4 gates at irreversible, preference-driven, or costly decision points
29
+
30
+ ## Gate Protocol
31
+
32
+ Present structured choices at gates. NEVER skip or proceed without user response.
33
+
34
+ **Format** — table of findings/options + lettered choices + your recommendation with 1-sentence rationale. For high-impact gates, add a SWOT table. See `references/code-organization-workflow.md` for full Gate examples.
35
+
36
+ **Rules**:
37
+ - If user says "do it all automatically", ask "confirm skip ALL gates?" first
38
+ - After user decides, execute automatically and report results with rollback instructions
25
39
 
26
40
  ## Standard Operating Procedure
27
41
 
@@ -34,43 +48,83 @@ Parse and validate `InputSchema` JSON via Zod. Read `src/schemas/input.schema.ts
34
48
  Run `scanCodebase(input)`. The scanner:
35
49
 
36
50
  1. Detect workspace roots for monorepo support
37
- 2. Match code against 20+ domain patterns (i18n, auth, state-management, etc.)
38
- 3. Record each detection with: file path, line range, pattern category, confidence score, domain
39
- 4. Return `ScanResult` with detections and workspace info
51
+ 2. Match code against 30+ domain patterns (i18n, auth, state-management, code-organization, etc.)
52
+ 3. Run structural analysis: design system layers (monorepo), code organization (all projects)
53
+ 4. Return `ScanResult` with:
54
+ - `detections` — hand-rolled code patterns found
55
+ - `structuralFindings` — architectural + code organization issues
56
+ - `codeOrganizationStats` — project-wide metrics (file counts, naming conventions, circular dep count)
57
+ - `workspaces` — monorepo workspace info
58
+
59
+ Detections and findings contain no recommendations — only facts.
40
60
 
41
- Detections contain no library suggestions — only what was detected and where.
61
+ ### GATE 1: Triage Detections
62
+
63
+ **Why**: Each accepted detection costs a Context7 verification call. False positives waste quota.
64
+
65
+ Present scan results as a triage table with columns: #, Domain, Pattern, File, Confidence, Action. Offer options: (A) accept all, (B) skip specific numbers, (C) high-confidence only. See `references/code-organization-workflow.md#gate-1-triage-example` for format.
66
+
67
+ Wait for user response. Proceed with accepted detections only.
42
68
 
43
69
  ### Step 2.5: Gap Analysis (AI Agent)
44
70
 
45
- Beyond scanner detections, analyze what the project is **missing entirely**. Inspect:
71
+ Analyze what the project is **missing entirely**:
72
+
73
+ 1. **Installed dependencies** — low-level tools that should be upgraded to platform-level solutions
74
+ 2. **Monorepo structure** — missing architectural layers (e.g., shared token package, shared config preset)
75
+ 3. **Cross-cutting concerns** — absent capabilities: structured logging, error monitoring, rate limiting, transactional email, type-safe API layer
76
+ 4. **Architecture patterns** — opportunities for multi-package solutions (e.g., design-tokens → tailwind-config → ui)
77
+
78
+ Analyze at three levels: **single library gap**, **ecosystem gap**, **architecture gap**.
79
+
80
+ Provide each gap as a `GapRecommendation`. Read `src/index.ts` for the interface.
81
+
82
+ **Design system gaps** — two paths:
83
+ - **No existing frontend**: Read `references/design-system-sources.md` for curated repos and sparse-checkout workflow.
84
+ - **Existing frontend**: Read `references/design-system-extraction.md` for extraction workflow, then `references/design-system-sources.md` for implementation.
85
+
86
+ ### Step 2.7: Code Organization Analysis
87
+
88
+ #### Phase A — Collect facts (MUST use tools, DO NOT estimate)
89
+
90
+ You cannot infer file counts, naming conventions, or import cycles from knowledge. You MUST read the filesystem.
91
+
92
+ **If using the npm library** — `scanResult.structuralFindings` and `scanResult.codeOrganizationStats` already contain all findings. Skip to Phase B.
93
+
94
+ **If not** — run the shell commands in `references/code-organization-workflow.md#phase-a-shell-commands-for-collecting-facts`.
46
95
 
47
- 1. **Installed dependencies** identify low-level tools that should be upgraded to platform-level solutions
48
- 2. **Monorepo structure** — identify missing architectural layers (e.g., shared token package, shared config preset)
49
- 3. **Cross-cutting concerns** — identify absent capabilities: structured logging, error monitoring, rate limiting, event-driven workflows, transactional email, type-safe API layer
50
- 4. **Architecture patterns** — identify opportunities for multi-package solutions (e.g., design-tokens → tailwind-config → ui three-layer architecture for design systems)
96
+ Record each finding with: **directory/file path, count, type**. These are facts.
51
97
 
52
- Analyze at three levels of depth:
53
- - **Single library gap**: missing one tool (e.g., no form validation library)
54
- - **Ecosystem gap**: missing a coordinated set of tools (e.g., no observability stack)
55
- - **Architecture gap**: missing an entire structural layer (e.g., no design system, no shared config)
98
+ #### Phase B Recommend solutions (use your knowledge + Context7)
56
99
 
57
- Provide each gap as a `GapRecommendation`. Read `src/index.ts` for the interface. Pass gaps via the `gaps` option in `analyze()`.
100
+ For each finding, apply the MUST do / MUST NOT do decision tree in `references/code-organization-workflow.md#phase-b-decision-tree`. Do NOT recommend tools without Context7 verification.
58
101
 
59
- **Design system gaps** Two paths depending on project maturity:
60
- - **No existing frontend**: Scaffold from reference repos. Read `references/design-system-sources.md` for curated sources and sparse-checkout workflow.
61
- - **Existing frontend without formal design system**: First extract the spec (audit → tokens → classify → document) via `references/design-system-extraction.md`, then implement the architecture via `references/design-system-sources.md`.
102
+ For worked examples showing the full Fact Read → Recommend flow, see `references/code-organization-workflow.md#phase-b-worked-examples`.
103
+
104
+ **Skip rules** skip a finding if:
105
+ - Directory is in `tests/`, `__tests__/`, `__mocks__/`, `fixtures/`, `generated/`, `.storybook/`
106
+ - File is auto-generated (has `// @generated` or `/* eslint-disable */` at top)
107
+ - Directory has <3 files (too few to judge)
108
+
109
+ ### GATE 2: Code Organization Preferences
110
+
111
+ **Why**: Organization pattern and naming convention are team preferences, not technical correctness.
112
+
113
+ Present only if structural findings exist. For each preference, present a SWOT comparison with lettered options. See `references/code-organization-workflow.md#gate-2-swot-examples` for format.
114
+
115
+ Wait for user response on each preference. Proceed to Step 3 with confirmed choices.
62
116
 
63
117
  ### Step 3: Recommend Solutions (AI Agent)
64
118
 
65
- For each scanner detection, recommend a **solution**. Consider:
119
+ For each accepted detection, recommend a **solution**:
66
120
 
67
- 1. **Stack coherence** — don't recommend libraries in isolation; consider how they fit the project's overall stack (e.g., recommending Stripe should trigger consideration of Resend for transactional email and PostHog for payment funnel analytics)
121
+ 1. **Stack coherence** — consider how libraries fit the project's overall stack
68
122
  2. **Ecosystem composition** — recommend companion libraries that work together
69
123
  3. **Rationale** — explain WHY this choice fits this project's framework, runtime, and scale
70
124
  4. **Anti-patterns** — what NOT to use and why
71
125
  5. **Alternatives** — different solutions for different architectural contexts
72
- 6. **Migration snippet** — for each recommendation, read the detected code (file path + line range from scanner) and generate a concrete before/after code example showing the migration
73
- 7. **Context7 verification** — call `resolve-library-id` + `query-docs` to confirm the library exists and get latest version/docs
126
+ 6. **Migration snippet** — read the detected code (file path + line range) and generate before/after examples
127
+ 7. **Context7 verification** — call `resolve-library-id` + `query-docs` to confirm existence and get latest docs
74
128
 
75
129
  Read `src/index.ts` for the `LibraryRecommendation` interface. Return `null` to skip a detection.
76
130
 
@@ -80,12 +134,20 @@ Read `src/index.ts` for the `LibraryRecommendation` interface. Return `null` to
80
134
  - Library is already in project dependencies (suggest version update instead)
81
135
  - Hand-rolled code is simpler than the library (3-line utility vs 50KB dep)
82
136
 
137
+ ### GATE 3: Accept/Reject Recommendations
138
+
139
+ **Why**: Each recommendation has real migration cost. User may have business, timeline, or architectural reasons to defer or reject.
140
+
141
+ Present ALL recommendations (replacements + gaps + code org tooling) as a decision table with columns: #, Domain, Replace what, With what, Risk, Effort, Context7, Decision. Offer options: (A) accept all, (B) accept specific, (C) low-risk only, (D) defer all. See `references/code-organization-workflow.md#gate-3-recommendation-table-example` for format.
142
+
143
+ Wait for user response. Rejected items are excluded from migration plan, scoring, and PRs.
144
+
83
145
  ### Step 4–7: Score, Plan, Audit, Serialize
84
146
 
85
147
  The pipeline handles these automatically:
86
- - **Scoring**: confidence-based dimension scores (overridable by AI agent via `dimensionHints`)
148
+ - **Scoring**: confidence-based dimension scores (overridable via `dimensionHints`)
87
149
  - **Migration plan**: auto-grouped by risk (low/medium/high), sorted by file co-location
88
- - **UX audit**: provide via `uxAudit` option in `analyze()`. Evaluate 8 categories: accessibility, error/empty/loading states, form validation, performance feel, copy consistency, design system alignment. For each, assess status (present/partial/missing) based on project code and `currentLibraries`.
150
+ - **UX audit**: provide via `uxAudit` option. Evaluate 8 categories (accessibility, error/empty/loading states, form validation, performance feel, copy consistency, design system alignment)
89
151
  - **Constraints**: license allowlist filtering, dependency conflict detection, JSON serialization
90
152
 
91
153
  ### Optional Steps
@@ -94,6 +156,22 @@ The pipeline handles these automatically:
94
156
  - **Step 9**: Auto-update existing dependencies (`registryClient`)
95
157
  - **Step 10**: PR auto-creation via GitHub/GitLab (`platformClient` + `gitOps`)
96
158
 
159
+ ### GATE 4: Before Irreversible Actions
160
+
161
+ **Why**: Creating PRs pushes branches to remote and notifies team members. File migrations modify the codebase. Both are irreversible.
162
+
163
+ Present only if Step 10 or file migration is about to execute. Show PR table and file migration table with rollback commands. Offer options: (A) execute all, (B) PRs only, (C) migration only, (D) dry run, (E) abort. See `references/code-organization-workflow.md#gate-4-execution-confirmation-example` for format.
164
+
165
+ Wait for user response. After execution, report results with rollback instructions.
166
+
167
+ ## MCP Integration
168
+
169
+ Prefer MCP tools when available; fall back to shell commands if not.
170
+
171
+ - **Context7 MCP** (required) — `resolve-library-id` + `query-docs` for library verification
172
+ - **GitHub MCP** (preferred for PRs) — structured PR create/update/query; fallback: `gh` CLI
173
+ - **Git MCP / GitKraken MCP** (preferred for scaffold) — structured repo browse/sparse-checkout; fallback: `git` CLI
174
+
97
175
  ## Output
98
176
 
99
177
  Single `OutputSchema` JSON containing:
@@ -0,0 +1,26 @@
1
+ import type { StructuralFinding } from './structure-analyzer.js';
2
+ export interface CodeOrganizationAnalysis {
3
+ findings: StructuralFinding[];
4
+ stats: {
5
+ totalSourceFiles: number;
6
+ maxDirectoryDepth: number;
7
+ /** Naming convention distribution: kebab → count, camelCase → count, etc. */
8
+ namingConventions: Record<string, number>;
9
+ circularDependencyCount: number;
10
+ };
11
+ }
12
+ /**
13
+ * Analyze project code organization for structural issues.
14
+ *
15
+ * Deterministic filesystem analysis that Claude cannot replicate:
16
+ * - Counts files per directory (god directories)
17
+ * - Reads filenames to check naming conventions
18
+ * - Measures directory nesting depth
19
+ * - Counts re-exports in barrel files
20
+ * - Builds import graph to detect circular dependencies
21
+ *
22
+ * Recommendations (which pattern to adopt, which tools to use)
23
+ * are the AI agent's responsibility.
24
+ */
25
+ export declare function analyzeCodeOrganization(repoPath: string): CodeOrganizationAnalysis;
26
+ //# sourceMappingURL=code-organization-analyzer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code-organization-analyzer.d.ts","sourceRoot":"","sources":["../../src/analyzer/code-organization-analyzer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAMjE,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,iBAAiB,EAAE,CAAC;IAC9B,KAAK,EAAE;QACL,gBAAgB,EAAE,MAAM,CAAC;QACzB,iBAAiB,EAAE,MAAM,CAAC;QAC1B,6EAA6E;QAC7E,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC1C,uBAAuB,EAAE,MAAM,CAAC;KACjC,CAAC;CACH;AAuND;;;;;;;;;;;;GAYG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,wBAAwB,CAmMlF"}
@@ -0,0 +1,389 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ // ---------------------------------------------------------------------------
4
+ // Constants — thresholds for code organization heuristics
5
+ //
6
+ // These thresholds are informed by the directory structures of
7
+ // Vercel (Next.js), Stripe (API docs), Linear, Supabase, shadcn/ui, Dub,
8
+ // and other reference Silicon Valley products. They represent the point
9
+ // where hand-rolled organization becomes unmaintainable and tools
10
+ // (eslint-plugin-import, knip, Barrel-file analyzers) are justified.
11
+ //
12
+ // Claude cannot determine these values without filesystem access.
13
+ // ---------------------------------------------------------------------------
14
+ /** Max source files in a single directory before it becomes a "god directory" */
15
+ const GOD_DIRECTORY_THRESHOLD = 15;
16
+ /** Max directory nesting depth from project root (src/) */
17
+ const MAX_NESTING_DEPTH = 5;
18
+ /** Max re-export lines in a barrel file */
19
+ const BARREL_BLOAT_THRESHOLD = 10;
20
+ /** Max files in a catch-all directory (utils/, helpers/, shared/, common/, lib/) */
21
+ const CATCH_ALL_THRESHOLD = 10;
22
+ /** Source file extensions to consider */
23
+ const SOURCE_EXTS = new Set(['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs']);
24
+ /** Directories to skip during analysis */
25
+ const SKIP_DIRS = new Set([
26
+ 'node_modules', '.git', 'dist', 'build', '.next', '__pycache__',
27
+ '.venv', 'venv', 'target', 'vendor', '.turbo', 'coverage',
28
+ ]);
29
+ /** Catch-all directory names that should be split by domain */
30
+ const CATCH_ALL_NAMES = new Set(['utils', 'helpers', 'common', 'shared', 'lib']);
31
+ function detectNamingConvention(filename) {
32
+ // Strip extension and any leading dot
33
+ const name = filename.replace(/\.[^.]+$/, '').replace(/^\./, '');
34
+ if (!name || name === 'index')
35
+ return 'unknown';
36
+ if (/^[A-Z][A-Z0-9_]+$/.test(name))
37
+ return 'SCREAMING_SNAKE';
38
+ if (/^[A-Z][a-zA-Z0-9]*$/.test(name))
39
+ return 'PascalCase';
40
+ if (/^[a-z][a-zA-Z0-9]*$/.test(name))
41
+ return 'camelCase';
42
+ if (/^[a-z][a-z0-9]*(-[a-z0-9]+)+$/.test(name))
43
+ return 'kebab-case';
44
+ if (/^[a-z][a-z0-9]*(_[a-z0-9]+)+$/.test(name))
45
+ return 'snake_case';
46
+ // Mixed patterns
47
+ if (name.includes('-'))
48
+ return 'kebab-case';
49
+ if (name.includes('_'))
50
+ return 'snake_case';
51
+ if (/^[A-Z]/.test(name))
52
+ return 'PascalCase';
53
+ return 'camelCase';
54
+ }
55
+ function* walkDirEntries(dir, repoPath) {
56
+ let entries;
57
+ try {
58
+ entries = fs.readdirSync(dir, { withFileTypes: true });
59
+ }
60
+ catch {
61
+ return;
62
+ }
63
+ for (const entry of entries) {
64
+ const fullPath = path.join(dir, entry.name);
65
+ const relativePath = path.relative(repoPath, fullPath);
66
+ if (entry.isDirectory()) {
67
+ if (!SKIP_DIRS.has(entry.name)) {
68
+ yield { name: entry.name, fullPath, relativePath, isDirectory: true };
69
+ yield* walkDirEntries(fullPath, repoPath);
70
+ }
71
+ }
72
+ else if (entry.isFile()) {
73
+ yield { name: entry.name, fullPath, relativePath, isDirectory: false };
74
+ }
75
+ }
76
+ }
77
+ // ---------------------------------------------------------------------------
78
+ // Import graph for circular dependency detection
79
+ // ---------------------------------------------------------------------------
80
+ /** Regex patterns to extract import/require paths from source files */
81
+ const IMPORT_PATTERNS = [
82
+ /(?:import\s+(?:[\s\S]*?\s+from\s+)?['"`])(\.{1,2}\/[^'"`\n]+)['"`]/g,
83
+ /(?:import\s*\(\s*['"`])(\.{1,2}\/[^'"`\n]+)['"`]/g,
84
+ /require\s*\(\s*['"`](\.{1,2}\/[^'"`\n]+)['"`]\s*\)/g,
85
+ /export\s+(?:\*|{[^}]*})\s+from\s+['"`](\.{1,2}\/[^'"`\n]+)['"`]/g,
86
+ ];
87
+ function extractImports(filePath) {
88
+ let content;
89
+ try {
90
+ content = fs.readFileSync(filePath, 'utf-8');
91
+ }
92
+ catch {
93
+ return [];
94
+ }
95
+ if (content.length > 500_000)
96
+ return [];
97
+ const imports = [];
98
+ for (const pattern of IMPORT_PATTERNS) {
99
+ // Reset regex state
100
+ const regex = new RegExp(pattern.source, pattern.flags);
101
+ let match;
102
+ while ((match = regex.exec(content)) !== null) {
103
+ if (match[1])
104
+ imports.push(match[1]);
105
+ }
106
+ }
107
+ return imports;
108
+ }
109
+ function resolveImportPath(fromFile, importPath) {
110
+ const fromDir = path.dirname(fromFile);
111
+ let resolved = path.resolve(fromDir, importPath);
112
+ // Try extensions if no extension present
113
+ const ext = path.extname(resolved);
114
+ if (!ext || !SOURCE_EXTS.has(ext)) {
115
+ for (const tryExt of ['.ts', '.tsx', '.js', '.jsx']) {
116
+ if (fs.existsSync(resolved + tryExt))
117
+ return resolved + tryExt;
118
+ }
119
+ // Try index file
120
+ const indexPath = path.join(resolved, 'index');
121
+ for (const tryExt of ['.ts', '.tsx', '.js', '.jsx']) {
122
+ if (fs.existsSync(indexPath + tryExt))
123
+ return indexPath + tryExt;
124
+ }
125
+ return null;
126
+ }
127
+ return fs.existsSync(resolved) ? resolved : null;
128
+ }
129
+ /**
130
+ * Detect circular dependencies using DFS cycle detection.
131
+ * Returns arrays of file paths forming cycles.
132
+ */
133
+ function detectCircularDependencies(sourceFiles, repoPath) {
134
+ // Build adjacency list
135
+ const graph = new Map();
136
+ for (const file of sourceFiles) {
137
+ const imports = extractImports(file);
138
+ const resolved = [];
139
+ for (const imp of imports) {
140
+ const target = resolveImportPath(file, imp);
141
+ if (target && sourceFiles.includes(target)) {
142
+ resolved.push(target);
143
+ }
144
+ }
145
+ graph.set(file, resolved);
146
+ }
147
+ // DFS cycle detection
148
+ const cycles = [];
149
+ const visited = new Set();
150
+ const onStack = new Set();
151
+ const pathStack = [];
152
+ const seen = new Set(); // deduplicate cycles
153
+ function dfs(node) {
154
+ visited.add(node);
155
+ onStack.add(node);
156
+ pathStack.push(node);
157
+ const neighbors = graph.get(node) ?? [];
158
+ for (const neighbor of neighbors) {
159
+ if (!visited.has(neighbor)) {
160
+ dfs(neighbor);
161
+ }
162
+ else if (onStack.has(neighbor)) {
163
+ // Found a cycle — extract it
164
+ const cycleStart = pathStack.indexOf(neighbor);
165
+ if (cycleStart >= 0) {
166
+ const cycle = pathStack.slice(cycleStart).map((f) => path.relative(repoPath, f));
167
+ const key = [...cycle].sort().join('|');
168
+ if (!seen.has(key)) {
169
+ seen.add(key);
170
+ cycles.push(cycle);
171
+ }
172
+ }
173
+ }
174
+ }
175
+ pathStack.pop();
176
+ onStack.delete(node);
177
+ }
178
+ for (const file of sourceFiles) {
179
+ if (!visited.has(file)) {
180
+ dfs(file);
181
+ }
182
+ }
183
+ return cycles;
184
+ }
185
+ // ---------------------------------------------------------------------------
186
+ // analyzeCodeOrganization — main entry point
187
+ // ---------------------------------------------------------------------------
188
+ /**
189
+ * Analyze project code organization for structural issues.
190
+ *
191
+ * Deterministic filesystem analysis that Claude cannot replicate:
192
+ * - Counts files per directory (god directories)
193
+ * - Reads filenames to check naming conventions
194
+ * - Measures directory nesting depth
195
+ * - Counts re-exports in barrel files
196
+ * - Builds import graph to detect circular dependencies
197
+ *
198
+ * Recommendations (which pattern to adopt, which tools to use)
199
+ * are the AI agent's responsibility.
200
+ */
201
+ export function analyzeCodeOrganization(repoPath) {
202
+ const findings = [];
203
+ const allSourceFiles = [];
204
+ const namingConventions = {};
205
+ // --- Collect directory info ---
206
+ const dirFileCount = new Map();
207
+ let maxDepth = 0;
208
+ for (const entry of walkDirEntries(repoPath, repoPath)) {
209
+ if (entry.isDirectory) {
210
+ // Track nesting depth
211
+ const depth = entry.relativePath.split(path.sep).length;
212
+ if (depth > maxDepth)
213
+ maxDepth = depth;
214
+ }
215
+ else {
216
+ const ext = path.extname(entry.name);
217
+ if (!SOURCE_EXTS.has(ext))
218
+ continue;
219
+ allSourceFiles.push(entry.fullPath);
220
+ // Track naming convention
221
+ const convention = detectNamingConvention(entry.name);
222
+ if (convention !== 'unknown') {
223
+ namingConventions[convention] = (namingConventions[convention] ?? 0) + 1;
224
+ }
225
+ // Track files per directory
226
+ const dir = path.dirname(entry.relativePath);
227
+ const existing = dirFileCount.get(dir);
228
+ if (existing) {
229
+ existing.count++;
230
+ existing.files.push(entry.name);
231
+ }
232
+ else {
233
+ dirFileCount.set(dir, { count: 1, files: [entry.name] });
234
+ }
235
+ }
236
+ }
237
+ // --- Check 1: God directories ---
238
+ for (const [dir, info] of dirFileCount) {
239
+ if (info.count > GOD_DIRECTORY_THRESHOLD) {
240
+ findings.push({
241
+ type: 'god-directory',
242
+ domain: 'code-organization',
243
+ description: `Directory "${dir}" contains ${info.count} source files (threshold: ${GOD_DIRECTORY_THRESHOLD}). Split by feature or domain.`,
244
+ paths: [dir],
245
+ severity: info.count > GOD_DIRECTORY_THRESHOLD * 2 ? 'critical' : 'warning',
246
+ metadata: { fileCount: info.count, threshold: GOD_DIRECTORY_THRESHOLD },
247
+ });
248
+ }
249
+ }
250
+ // --- Check 2: Mixed naming conventions per directory ---
251
+ for (const [dir, info] of dirFileCount) {
252
+ if (info.files.length < 3)
253
+ continue; // need enough files to judge
254
+ const conventions = new Map();
255
+ for (const file of info.files) {
256
+ const conv = detectNamingConvention(file);
257
+ if (conv === 'unknown')
258
+ continue;
259
+ const list = conventions.get(conv) ?? [];
260
+ list.push(file);
261
+ conventions.set(conv, list);
262
+ }
263
+ // Filter out conventions with only 1 file (noise)
264
+ const significant = [...conventions.entries()].filter(([, files]) => files.length >= 2);
265
+ if (significant.length >= 2) {
266
+ const summary = significant
267
+ .map(([conv, files]) => `${conv} (${files.length} files)`)
268
+ .join(', ');
269
+ findings.push({
270
+ type: 'mixed-naming-convention',
271
+ domain: 'code-organization',
272
+ description: `Directory "${dir}" uses mixed naming conventions: ${summary}. Choose one convention and enforce it.`,
273
+ paths: [dir],
274
+ severity: 'warning',
275
+ metadata: {
276
+ conventions: Object.fromEntries(significant.map(([k, v]) => [k, v.length])),
277
+ },
278
+ });
279
+ }
280
+ }
281
+ // --- Check 3: Deep nesting ---
282
+ for (const entry of walkDirEntries(repoPath, repoPath)) {
283
+ if (!entry.isDirectory)
284
+ continue;
285
+ const parts = entry.relativePath.split(path.sep);
286
+ // Only measure from src/ or packages/ onwards
287
+ const srcIdx = parts.indexOf('src');
288
+ const depth = srcIdx >= 0 ? parts.length - srcIdx : parts.length;
289
+ if (depth > MAX_NESTING_DEPTH) {
290
+ findings.push({
291
+ type: 'deep-nesting',
292
+ domain: 'code-organization',
293
+ description: `Directory "${entry.relativePath}" is ${depth} levels deep (max: ${MAX_NESTING_DEPTH}). Consider flattening or using path aliases.`,
294
+ paths: [entry.relativePath],
295
+ severity: 'warning',
296
+ metadata: { depth, threshold: MAX_NESTING_DEPTH },
297
+ });
298
+ }
299
+ }
300
+ // --- Check 4: Barrel bloat (index files with many re-exports) ---
301
+ for (const file of allSourceFiles) {
302
+ const basename = path.basename(file, path.extname(file));
303
+ if (basename !== 'index')
304
+ continue;
305
+ let content;
306
+ try {
307
+ content = fs.readFileSync(file, 'utf-8');
308
+ }
309
+ catch {
310
+ continue;
311
+ }
312
+ const reexportCount = (content.match(/export\s+(?:\*|{[^}]*})\s+from\s+['"`]/g) ?? []).length;
313
+ if (reexportCount > BARREL_BLOAT_THRESHOLD) {
314
+ const relativePath = path.relative(repoPath, file);
315
+ findings.push({
316
+ type: 'barrel-bloat',
317
+ domain: 'code-organization',
318
+ description: `Barrel file "${relativePath}" has ${reexportCount} re-exports (threshold: ${BARREL_BLOAT_THRESHOLD}). Consider direct imports or code-splitting.`,
319
+ paths: [relativePath],
320
+ severity: reexportCount > BARREL_BLOAT_THRESHOLD * 2 ? 'critical' : 'warning',
321
+ metadata: { reexportCount, threshold: BARREL_BLOAT_THRESHOLD },
322
+ });
323
+ }
324
+ }
325
+ // --- Check 5: Catch-all directories ---
326
+ for (const [dir, info] of dirFileCount) {
327
+ const dirName = path.basename(dir);
328
+ if (!CATCH_ALL_NAMES.has(dirName))
329
+ continue;
330
+ if (info.count > CATCH_ALL_THRESHOLD) {
331
+ findings.push({
332
+ type: 'catch-all-directory',
333
+ domain: 'code-organization',
334
+ description: `Catch-all directory "${dir}" contains ${info.count} files (threshold: ${CATCH_ALL_THRESHOLD}). Split into domain-specific modules (e.g., utils/date, utils/string, utils/validation).`,
335
+ paths: [dir],
336
+ severity: info.count > CATCH_ALL_THRESHOLD * 2 ? 'critical' : 'warning',
337
+ metadata: { fileCount: info.count, threshold: CATCH_ALL_THRESHOLD },
338
+ });
339
+ }
340
+ }
341
+ // --- Check 6: Mixed export styles (default + multiple named in same file) ---
342
+ for (const file of allSourceFiles) {
343
+ const basename = path.basename(file, path.extname(file));
344
+ if (basename === 'index')
345
+ continue; // barrel files are expected to have many exports
346
+ let content;
347
+ try {
348
+ content = fs.readFileSync(file, 'utf-8');
349
+ }
350
+ catch {
351
+ continue;
352
+ }
353
+ const hasDefaultExport = /export\s+default\s/.test(content);
354
+ const namedExportCount = (content.match(/export\s+(?:function|class|const|let|var|enum|type|interface)\s+\w/g) ?? []).length;
355
+ if (hasDefaultExport && namedExportCount >= 3) {
356
+ const relativePath = path.relative(repoPath, file);
357
+ findings.push({
358
+ type: 'god-directory', // reuse closest type — file is a "god module"
359
+ domain: 'code-organization',
360
+ description: `File "${relativePath}" mixes a default export with ${namedExportCount} named exports. One module, one responsibility — split into separate files.`,
361
+ paths: [relativePath],
362
+ severity: 'info',
363
+ metadata: { hasDefaultExport, namedExportCount, issue: 'mixed-export-style' },
364
+ });
365
+ }
366
+ }
367
+ // --- Check 7: Circular dependencies ---
368
+ const cycles = detectCircularDependencies(allSourceFiles, repoPath);
369
+ for (const cycle of cycles) {
370
+ findings.push({
371
+ type: 'circular-dependency',
372
+ domain: 'code-organization',
373
+ description: `Circular dependency detected: ${cycle.join(' → ')} → ${cycle[0]}`,
374
+ paths: cycle,
375
+ severity: cycle.length > 3 ? 'critical' : 'warning',
376
+ metadata: { cycleLength: cycle.length },
377
+ });
378
+ }
379
+ return {
380
+ findings,
381
+ stats: {
382
+ totalSourceFiles: allSourceFiles.length,
383
+ maxDirectoryDepth: maxDepth,
384
+ namingConventions,
385
+ circularDependencyCount: cycles.length,
386
+ },
387
+ };
388
+ }
389
+ //# sourceMappingURL=code-organization-analyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code-organization-analyzer.js","sourceRoot":"","sources":["../../src/analyzer/code-organization-analyzer.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"pattern-catalog.d.ts","sourceRoot":"","sources":["../../src/analyzer/pattern-catalog.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAEnE;;;;;;;;;GASG;AACH,MAAM,WAAW,iBAAiB;IAChC,6EAA6E;IAC7E,EAAE,EAAE,MAAM,CAAC;IACX,qDAAqD;IACrD,MAAM,EAAE,gBAAgB,CAAC;IACzB,8DAA8D;IAC9D,WAAW,EAAE,MAAM,CAAC;IACpB,sCAAsC;IACtC,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,+CAA+C;IAC/C,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,mDAAmD;IACnD,cAAc,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,IAAI,iBAAiB,EAAE,CAkqBvD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAExE"}
1
+ {"version":3,"file":"pattern-catalog.d.ts","sourceRoot":"","sources":["../../src/analyzer/pattern-catalog.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAEnE;;;;;;;;;GASG;AACH,MAAM,WAAW,iBAAiB;IAChC,6EAA6E;IAC7E,EAAE,EAAE,MAAM,CAAC;IACX,qDAAqD;IACrD,MAAM,EAAE,gBAAgB,CAAC;IACzB,8DAA8D;IAC9D,WAAW,EAAE,MAAM,CAAC;IACpB,sCAAsC;IACtC,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,+CAA+C;IAC/C,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,mDAAmD;IACnD,cAAc,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,IAAI,iBAAiB,EAAE,CAmsBvD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAExE"}