pumuki-ast-hooks 5.5.47 → 5.5.49

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.
Files changed (31) hide show
  1. package/docs/CODE_STANDARDS.md +5 -0
  2. package/docs/VIOLATIONS_RESOLUTION_PLAN.md +5 -140
  3. package/package.json +1 -1
  4. package/scripts/hooks-system/.audit_tmp/hook-metrics.jsonl +96 -0
  5. package/scripts/hooks-system/application/services/installation/VSCodeTaskConfigurator.js +3 -1
  6. package/scripts/hooks-system/bin/gitflow-cycle.js +0 -0
  7. package/scripts/hooks-system/config/project.config.json +1 -1
  8. package/scripts/hooks-system/infrastructure/ast/android/analyzers/AndroidSOLIDAnalyzer.js +11 -255
  9. package/scripts/hooks-system/infrastructure/ast/android/detectors/android-solid-detectors.js +227 -0
  10. package/scripts/hooks-system/infrastructure/ast/ast-core.js +12 -3
  11. package/scripts/hooks-system/infrastructure/ast/ast-intelligence.js +36 -13
  12. package/scripts/hooks-system/infrastructure/ast/backend/ast-backend.js +10 -83
  13. package/scripts/hooks-system/infrastructure/ast/backend/detectors/god-class-detector.js +83 -0
  14. package/scripts/hooks-system/infrastructure/ast/common/ast-common.js +17 -2
  15. package/scripts/hooks-system/infrastructure/ast/frontend/analyzers/FrontendArchitectureDetector.js +12 -142
  16. package/scripts/hooks-system/infrastructure/ast/frontend/detectors/frontend-architecture-strategies.js +126 -0
  17. package/scripts/hooks-system/infrastructure/ast/ios/analyzers/iOSASTIntelligentAnalyzer.js +30 -783
  18. package/scripts/hooks-system/infrastructure/ast/ios/analyzers/iOSArchitectureDetector.js +21 -224
  19. package/scripts/hooks-system/infrastructure/ast/ios/analyzers/iOSArchitectureRules.js +18 -605
  20. package/scripts/hooks-system/infrastructure/ast/ios/analyzers/iOSModernPracticesRules.js +4 -1
  21. package/scripts/hooks-system/infrastructure/ast/ios/ast-ios.js +4 -1
  22. package/scripts/hooks-system/infrastructure/ast/ios/detectors/ios-architecture-rules-strategies.js +595 -0
  23. package/scripts/hooks-system/infrastructure/ast/ios/detectors/ios-architecture-strategies.js +192 -0
  24. package/scripts/hooks-system/infrastructure/ast/ios/detectors/ios-ast-intelligent-strategies.js +789 -0
  25. package/scripts/hooks-system/infrastructure/ast/ios/detectors/ios-god-class-detector.js +79 -0
  26. package/scripts/hooks-system/infrastructure/ast/ios/native-bridge.js +4 -1
  27. package/scripts/hooks-system/infrastructure/orchestration/intelligent-audit.js +24 -13
  28. package/skills/android-guidelines/SKILL.md +1 -0
  29. package/skills/backend-guidelines/SKILL.md +1 -0
  30. package/skills/frontend-guidelines/SKILL.md +1 -0
  31. package/skills/ios-guidelines/SKILL.md +1 -0
@@ -1,6 +1,13 @@
1
1
  const fs = require('fs');
2
2
  const path = require('path');
3
3
  const glob = require('glob');
4
+ const {
5
+ detectFeatureFirstClean,
6
+ detectComponentBased,
7
+ detectAtomicDesign,
8
+ detectStateManagement,
9
+ detectMVC,
10
+ } = require('../detectors/frontend-architecture-strategies');
4
11
 
5
12
  class FrontendArchitectureDetector {
6
13
  constructor(projectRoot) {
@@ -62,161 +69,24 @@ class FrontendArchitectureDetector {
62
69
  }
63
70
 
64
71
  detectFeatureFirstClean(files) {
65
- const hasFeaturesFolders = files.some(f =>
66
- /\/features?\/\w+\/(domain|application|infrastructure|presentation)\//.test(f)
67
- );
68
-
69
- const cleanArchFolders = ['domain', 'application', 'infrastructure', 'presentation'];
70
- const foundCleanFolders = cleanArchFolders.filter(folder => {
71
- return files.some(f => f.includes(`/${folder}/`));
72
- });
73
-
74
- const dddConcepts = files.filter(f =>
75
- f.includes('/entities/') ||
76
- f.includes('/value-objects/') ||
77
- f.includes('/use-cases/') ||
78
- f.includes('/repositories/') ||
79
- f.includes('Entity.ts') ||
80
- f.includes('UseCase.ts') ||
81
- f.includes('Repository.ts')
82
- );
83
-
84
- if (hasFeaturesFolders) {
85
- this.patterns.featureFirstClean += 10;
86
- }
87
-
88
- if (foundCleanFolders.length >= 3) {
89
- this.patterns.featureFirstClean += foundCleanFolders.length * 3;
90
- }
91
-
92
- if (dddConcepts.length > 0) {
93
- this.patterns.featureFirstClean += dddConcepts.length * 2;
94
- }
95
-
96
- const featureNames = new Set();
97
- files.forEach(f => {
98
- const match = f.match(/\/features?\/(\w+)\//);
99
- if (match) {
100
- featureNames.add(match[1]);
101
- }
102
- });
103
-
104
- if (featureNames.size >= 2) {
105
- this.patterns.featureFirstClean += featureNames.size * 4;
106
- }
107
-
108
- files.forEach(file => {
109
- const content = this.readFile(file);
110
-
111
- if (file.includes('/domain/') && content.includes('interface ') && content.includes('Repository')) {
112
- this.patterns.featureFirstClean += 3;
113
- }
114
-
115
- if (file.includes('/application/') || file.includes('/use-cases/')) {
116
- if (content.includes('UseCase') || content.includes('useCase')) {
117
- this.patterns.featureFirstClean += 2;
118
- }
119
- }
120
-
121
- if (file.includes('/hooks/') && file.includes('use') && file.endsWith('.ts')) {
122
- this.patterns.featureFirstClean += 1;
123
- }
124
- });
125
-
72
+ detectFeatureFirstClean(this.projectRoot, files, this.patterns);
126
73
  console.log(`[Architecture Detection] Feature-First + Clean + DDD score: ${this.patterns.featureFirstClean}`);
127
74
  }
128
75
 
129
76
  detectComponentBased(files) {
130
- const hasComponentsFolder = files.some(f => f.includes('/components/'));
131
-
132
- if (hasComponentsFolder) {
133
- this.patterns.componentBased += 10;
134
- }
135
-
136
- const componentFiles = files.filter(f =>
137
- f.includes('/components/') && (f.endsWith('.tsx') || f.endsWith('.jsx'))
138
- );
139
-
140
- if (componentFiles.length > 0) {
141
- this.patterns.componentBased += componentFiles.length;
142
- }
143
-
144
- files.forEach(file => {
145
- if (!file.includes('/components/')) return;
146
-
147
- const content = this.readFile(file);
148
- const componentImports = content.match(/from\s+['"]\.\.\/components\//g) || [];
149
-
150
- if (componentImports.length > 0) {
151
- this.patterns.componentBased += componentImports.length;
152
- }
153
- });
77
+ detectComponentBased(this.projectRoot, files, this.patterns);
154
78
  }
155
79
 
156
80
  detectAtomicDesign(files) {
157
- const atomicFolders = ['atoms', 'molecules', 'organisms', 'templates', 'pages'];
158
-
159
- const foundFolders = atomicFolders.filter(folder => {
160
- return files.some(f => f.includes(`/${folder}/`));
161
- });
162
-
163
- if (foundFolders.length >= 3) {
164
- this.patterns.atomicDesign += foundFolders.length * 5;
165
- }
166
-
167
- if (files.some(f => f.includes('/atoms/')) &&
168
- files.some(f => f.includes('/molecules/')) &&
169
- files.some(f => f.includes('/organisms/'))) {
170
- this.patterns.atomicDesign += 10;
171
- }
81
+ detectAtomicDesign(this.projectRoot, files, this.patterns);
172
82
  }
173
83
 
174
84
  detectStateManagement(files) {
175
- files.forEach(file => {
176
- const content = this.readFile(file);
177
-
178
- if (content.includes('zustand') || content.includes('create(') && file.includes('store')) {
179
- this.patterns.stateManagement += 5;
180
- }
181
-
182
- if (content.includes('redux') || content.includes('@reduxjs/toolkit') ||
183
- file.includes('slice') || file.includes('reducer')) {
184
- this.patterns.stateManagement += 5;
185
- }
186
-
187
- if (content.includes('createContext') || content.includes('Context.Provider')) {
188
- this.patterns.stateManagement += 2;
189
- }
190
-
191
- if (file.includes('/stores/') || file.includes('/state/')) {
192
- this.patterns.stateManagement += 3;
193
- }
194
- });
85
+ detectStateManagement(this.projectRoot, files, this.patterns);
195
86
  }
196
87
 
197
88
  detectMVC(files) {
198
- files.forEach(file => {
199
- if (!file.includes('component') && !file.endsWith('.tsx') && !file.endsWith('.jsx')) return;
200
-
201
- const content = this.readFile(file);
202
-
203
- if (content.includes('fetch(') || content.includes('axios.') || content.includes('.get(')) {
204
- const hasHook = files.some(f =>
205
- f.includes('use') && f.endsWith('.ts') && !f.includes('component')
206
- );
207
- const hasService = files.some(f =>
208
- f.includes('service') || f.includes('api')
209
- );
210
-
211
- if (!hasHook && !hasService) {
212
- this.patterns.mvc += 3;
213
- }
214
- }
215
-
216
- if (content.match(/const\s+\w+\s*=\s*\(.*\)\s*=>\s*{[\s\S]{0,500}if\s*\(.*\)\s*{[\s\S]{0,500}if\s*\(.*\)\s*{[\s\S]{0,500}if\s*\(.*\)\s*{/)) {
217
- this.patterns.mvc += 2;
218
- }
219
- });
89
+ detectMVC(this.projectRoot, files, this.patterns);
220
90
  }
221
91
 
222
92
  readFile(relativePath) {
@@ -0,0 +1,126 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ function readFileSafe(projectRoot, relativeOrAbsolutePath) {
5
+ try {
6
+ const filePath = path.isAbsolute(relativeOrAbsolutePath)
7
+ ? relativeOrAbsolutePath
8
+ : path.join(projectRoot, relativeOrAbsolutePath);
9
+ return fs.readFileSync(filePath, 'utf-8');
10
+ } catch (error) {
11
+ if (process.env.DEBUG) {
12
+ console.debug(`[FrontendArchitectureDetector] Failed to read file ${relativeOrAbsolutePath}: ${error.message}`);
13
+ }
14
+ return '';
15
+ }
16
+ }
17
+
18
+ function detectFeatureFirstClean(projectRoot, files, patterns) {
19
+ const hasFeaturesFolders = files.some(f =>
20
+ /\/features?\/\w+\/(domain|application|infrastructure|presentation)\//i.test(f)
21
+ );
22
+
23
+ const cleanArchFolders = ['domain', 'application', 'infrastructure', 'presentation'];
24
+ const foundCleanFolders = cleanArchFolders.filter(folder => {
25
+ return files.some(f => f.toLowerCase().includes(`/${folder}/`));
26
+ });
27
+
28
+ const dddConcepts = files.filter(f =>
29
+ f.includes('/entities/') ||
30
+ f.includes('/value-objects/') ||
31
+ f.includes('/use-cases/') ||
32
+ f.includes('/repositories/') ||
33
+ f.includes('Entity.ts') ||
34
+ f.includes('UseCase.ts') ||
35
+ f.includes('Repository.ts')
36
+ );
37
+
38
+ if (hasFeaturesFolders) {
39
+ patterns.featureFirstClean += 10;
40
+ }
41
+
42
+ if (foundCleanFolders.length >= 3) {
43
+ patterns.featureFirstClean += foundCleanFolders.length * 3;
44
+ }
45
+
46
+ if (dddConcepts.length > 0) {
47
+ patterns.featureFirstClean += dddConcepts.length * 2;
48
+ }
49
+
50
+ const featureNames = new Set();
51
+ files.forEach(f => {
52
+ const match = f.match(/\/features?\/(\w+)\//i);
53
+ if (match) {
54
+ featureNames.add(match[1]);
55
+ }
56
+ });
57
+
58
+ if (featureNames.size >= 2) {
59
+ patterns.featureFirstClean += featureNames.size * 4;
60
+ }
61
+
62
+ files.forEach(file => {
63
+ const content = readFileSafe(projectRoot, file);
64
+
65
+ if (file.toLowerCase().includes('/domain/') && content.includes('interface ') && content.includes('Repository')) {
66
+ patterns.featureFirstClean += 3;
67
+ }
68
+
69
+ if (file.toLowerCase().includes('/application/') || file.toLowerCase().includes('/use-cases/')) {
70
+ if (content.includes('UseCase') || content.includes('useCase')) {
71
+ patterns.featureFirstClean += 2;
72
+ }
73
+ }
74
+
75
+ if (/\/features?\/\w+\/presentation\//i.test(file) && /Page|Screen|View|Component/.test(content)) {
76
+ patterns.featureFirstClean += 1;
77
+ }
78
+ });
79
+ }
80
+
81
+ function detectComponentBased(_projectRoot, files, patterns) {
82
+ const componentPatterns = [
83
+ /\/components?\//i,
84
+ /\/ui\//i,
85
+ /\/widgets?\//i
86
+ ];
87
+
88
+ files.forEach(file => {
89
+ if (componentPatterns.some(p => p.test(file))) {
90
+ patterns.componentBased += 2;
91
+ }
92
+ });
93
+ }
94
+
95
+ function detectAtomicDesign(_projectRoot, files, patterns) {
96
+ const atomicFolders = ['atoms', 'molecules', 'organisms', 'templates', 'pages'];
97
+ const foundAtomic = atomicFolders.filter(folder =>
98
+ files.some(f => f.toLowerCase().includes(`/${folder}/`))
99
+ );
100
+
101
+ if (foundAtomic.length >= 3) {
102
+ patterns.atomicDesign += foundAtomic.length * 2;
103
+ }
104
+ }
105
+
106
+ function detectStateManagement(_projectRoot, files, patterns) {
107
+ const stateKeywords = ['redux', 'zustand', 'mobx', 'recoil', 'xstate', 'jotai', 'effector'];
108
+ if (files.some(f => stateKeywords.some(k => f.toLowerCase().includes(k)))) {
109
+ patterns.stateManagement += 5;
110
+ }
111
+ }
112
+
113
+ function detectMVC(_projectRoot, files, patterns) {
114
+ const controllerFiles = files.filter(f => /Controller\.(ts|tsx|jsx)$/i.test(f));
115
+ if (controllerFiles.length > 0) {
116
+ patterns.mvc += controllerFiles.length;
117
+ }
118
+ }
119
+
120
+ module.exports = {
121
+ detectFeatureFirstClean,
122
+ detectComponentBased,
123
+ detectAtomicDesign,
124
+ detectStateManagement,
125
+ detectMVC,
126
+ };