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,12 +1,22 @@
1
1
  const fs = require('fs');
2
2
  const path = require('path');
3
3
  const glob = require('glob');
4
+ const {
5
+ detectFeatureFirstClean,
6
+ detectTCA,
7
+ detectVIPER,
8
+ detectCleanSwift,
9
+ detectMVP,
10
+ detectMVVMC,
11
+ detectMVVM,
12
+ detectMVC,
13
+ } = require('../detectors/ios-architecture-strategies');
4
14
 
5
15
  class iOSArchitectureDetector {
6
16
  constructor(projectRoot) {
7
17
  this.projectRoot = projectRoot;
8
18
  this.patterns = {
9
- featureFirstClean: 0,
19
+ featureFirstClean: 0,
10
20
  mvvm: 0,
11
21
  mvvmc: 0,
12
22
  mvp: 0,
@@ -62,249 +72,36 @@ class iOSArchitectureDetector {
62
72
  }
63
73
 
64
74
  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('Entity.swift') ||
79
- f.includes('VO.swift') ||
80
- f.includes('UseCase.swift')
81
- );
82
-
83
- if (hasFeaturesFolders) {
84
- this.patterns.featureFirstClean += 10;
85
- }
86
-
87
- if (foundCleanFolders.length >= 3) {
88
- this.patterns.featureFirstClean += foundCleanFolders.length * 3;
89
- }
90
-
91
- if (dddConcepts.length > 0) {
92
- this.patterns.featureFirstClean += dddConcepts.length * 2;
93
- }
94
-
95
- const featureNames = new Set();
96
- files.forEach(f => {
97
- const match = f.match(/\/Features?\/(\w+)\//);
98
- if (match) {
99
- featureNames.add(match[1]);
100
- }
101
- });
102
-
103
- if (featureNames.size >= 2) {
104
- this.patterns.featureFirstClean += featureNames.size * 4;
105
- }
106
-
107
- files.forEach(file => {
108
- const content = this.readFile(file);
109
-
110
- if (content.includes('struct ') && content.includes('VO')) {
111
- this.patterns.featureFirstClean += 2;
112
- }
113
-
114
- if (file.includes('Entity.swift') && content.includes('func ')) {
115
- this.patterns.featureFirstClean += 2;
116
- }
117
-
118
- if (file.includes('/domain/') && content.includes('protocol ') && content.includes('Repository')) {
119
- this.patterns.featureFirstClean += 3;
120
- }
121
-
122
- if (file.includes('/application/') && content.includes('UseCase')) {
123
- this.patterns.featureFirstClean += 2;
124
- }
125
- });
126
-
75
+ detectFeatureFirstClean(files, this.patterns, this.projectRoot);
127
76
  console.log(`[Architecture Detection] Feature-First + Clean + DDD score: ${this.patterns.featureFirstClean}`);
128
77
  }
129
78
 
130
79
  detectTCA(files) {
131
- const tcaIndicators = [
132
- 'import ComposableArchitecture',
133
- 'Store<',
134
- 'struct.*State',
135
- 'enum.*Action',
136
- ': Reducer',
137
- 'Effect<'
138
- ];
139
-
140
- files.forEach(file => {
141
- const content = this.readFile(file);
142
- const matches = tcaIndicators.filter(indicator =>
143
- new RegExp(indicator).test(content)
144
- ).length;
145
-
146
- if (matches >= 3) {
147
- this.patterns.tca += matches;
148
- }
149
- });
80
+ detectTCA(files, this.patterns);
150
81
  }
151
82
 
152
83
  detectVIPER(files) {
153
- const viperFiles = files.filter(f =>
154
- /Presenter\.swift$|Interactor\.swift$|Router\.swift$|Entity\.swift$/.test(f)
155
- );
156
-
157
- if (viperFiles.length >= 4) {
158
- this.patterns.viper += viperFiles.length;
159
- }
160
-
161
- files.forEach(file => {
162
- const content = this.readFile(file);
163
- const viperProtocols = [
164
- 'ViewProtocol',
165
- 'PresenterProtocol',
166
- 'InteractorProtocol',
167
- 'RouterProtocol'
168
- ];
169
-
170
- const matches = viperProtocols.filter(proto =>
171
- content.includes(proto)
172
- ).length;
173
-
174
- if (matches >= 2) {
175
- this.patterns.viper += matches * 2;
176
- }
177
- });
178
-
179
- const viperFolders = ['View', 'Interactor', 'Presenter', 'Entity', 'Router'];
180
- const hasViperStructure = viperFolders.filter(folder => {
181
- const folderPath = path.join(this.projectRoot, folder);
182
- return fs.existsSync(folderPath);
183
- }).length;
184
-
185
- if (hasViperStructure >= 3) {
186
- this.patterns.viper += hasViperStructure * 3;
187
- }
84
+ detectVIPER(files, this.patterns, this.projectRoot);
188
85
  }
189
86
 
190
87
  detectCleanSwift(files) {
191
- const cleanSwiftFiles = files.filter(f =>
192
- /Models\.swift$/.test(f)
193
- );
194
-
195
- files.forEach(file => {
196
- const content = this.readFile(file);
197
- const cleanSwiftIndicators = [
198
- 'DisplayLogic',
199
- 'BusinessLogic',
200
- 'PresentationLogic',
201
- 'Request\\s*{',
202
- 'Response\\s*{',
203
- 'ViewModel\\s*{'
204
- ];
205
-
206
- const matches = cleanSwiftIndicators.filter(indicator =>
207
- new RegExp(indicator).test(content)
208
- ).length;
209
-
210
- if (matches >= 3) {
211
- this.patterns.cleanSwift += matches * 2;
212
- }
213
- });
88
+ detectCleanSwift(files, this.patterns);
214
89
  }
215
90
 
216
91
  detectMVP(files) {
217
- const presenterFiles = files.filter(f => /Presenter\.swift$/.test(f));
218
- const interactorFiles = files.filter(f => /Interactor\.swift$/.test(f));
219
- const routerFiles = files.filter(f => /Router\.swift$/.test(f));
220
-
221
- if (presenterFiles.length >= 2 && interactorFiles.length === 0 && routerFiles.length === 0) {
222
- this.patterns.mvp += presenterFiles.length * 3;
223
- }
224
-
225
- files.forEach(file => {
226
- const content = this.readFile(file);
227
-
228
- const hasMVPProtocols =
229
- content.includes('ViewProtocol') &&
230
- content.includes('PresenterProtocol') &&
231
- !content.includes('InteractorProtocol');
232
-
233
- if (hasMVPProtocols) {
234
- this.patterns.mvp += 3;
235
- }
236
- });
92
+ detectMVP(files, this.patterns);
237
93
  }
238
94
 
239
95
  detectMVVMC(files) {
240
- const coordinatorFiles = files.filter(f => /Coordinator\.swift$/.test(f));
241
-
242
- if (coordinatorFiles.length >= 1) {
243
- this.patterns.mvvmc += coordinatorFiles.length * 3;
244
- }
245
-
246
- files.forEach(file => {
247
- const content = this.readFile(file);
248
-
249
- if (content.includes('protocol Coordinator') ||
250
- content.includes(': Coordinator') ||
251
- /func\s+start\(\)/.test(content) && /func\s+navigate/.test(content)) {
252
- this.patterns.mvvmc += 2;
253
- }
254
- });
96
+ detectMVVMC(files, this.patterns);
255
97
  }
256
98
 
257
99
  detectMVVM(files) {
258
- const viewModelFiles = files.filter(f => /ViewModel\.swift$/.test(f));
259
-
260
- if (viewModelFiles.length >= 2) {
261
- this.patterns.mvvm += viewModelFiles.length * 2;
262
- }
263
-
264
- files.forEach(file => {
265
- const content = this.readFile(file);
266
-
267
- const mvvmIndicators = [
268
- '@Published',
269
- ': ObservableObject',
270
- 'import Combine',
271
- 'class.*ViewModel'
272
- ];
273
-
274
- const matches = mvvmIndicators.filter(indicator =>
275
- new RegExp(indicator).test(content)
276
- ).length;
277
-
278
- if (matches >= 2) {
279
- this.patterns.mvvm += matches;
280
- }
281
- });
100
+ detectMVVM(files, this.patterns);
282
101
  }
283
102
 
284
103
  detectMVC(files) {
285
- const viewControllerFiles = files.filter(f => /ViewController\.swift$/.test(f));
286
- const viewModelFiles = files.filter(f => /ViewModel\.swift$/.test(f));
287
- const presenterFiles = files.filter(f => /Presenter\.swift$/.test(f));
288
- const interactorFiles = files.filter(f => /Interactor\.swift$/.test(f));
289
-
290
- if (viewControllerFiles.length >= 2 &&
291
- viewModelFiles.length === 0 &&
292
- presenterFiles.length === 0 &&
293
- interactorFiles.length === 0) {
294
-
295
- viewControllerFiles.forEach(file => {
296
- const content = this.readFile(file);
297
- const lines = content.split('\n').length;
298
-
299
- if (lines > 300) {
300
- this.patterns.mvc += 3;
301
- } else if (lines > 150) {
302
- this.patterns.mvc += 2;
303
- } else {
304
- this.patterns.mvc += 1;
305
- }
306
- });
307
- }
104
+ detectMVC(files, this.patterns);
308
105
  }
309
106
 
310
107
  getDominantPattern() {
@@ -323,7 +120,7 @@ class iOSArchitectureDetector {
323
120
  }
324
121
 
325
122
  if (sorted.length > 1 && sorted[1][1] >= dominantScore * 0.7) {
326
- return 'MIXED';
123
+ return 'MIXED';
327
124
  }
328
125
 
329
126
  return this.normalizePatternName(dominant);
@@ -331,7 +128,7 @@ class iOSArchitectureDetector {
331
128
 
332
129
  normalizePatternName(pattern) {
333
130
  const mapping = {
334
- 'featureFirstClean': 'FEATURE_FIRST_CLEAN_DDD',
131
+ 'featureFirstClean': 'FEATURE_FIRST_CLEAN_DDD',
335
132
  'mvvm': 'MVVM',
336
133
  'mvvmc': 'MVVM-C',
337
134
  'mvp': 'MVP',