pumuki-ast-hooks 5.5.51 → 5.5.52

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 (38) hide show
  1. package/docs/MCP_SERVERS.md +16 -2
  2. package/docs/RELEASE_NOTES.md +34 -0
  3. package/hooks/git-status-monitor.ts +0 -5
  4. package/hooks/notify-macos.ts +0 -1
  5. package/hooks/pre-tool-use-evidence-validator.ts +0 -1
  6. package/package.json +2 -2
  7. package/scripts/hooks-system/.audit_tmp/hook-metrics.jsonl +48 -0
  8. package/scripts/hooks-system/application/services/guard/GuardConfig.js +2 -4
  9. package/scripts/hooks-system/application/services/installation/GitEnvironmentService.js +2 -20
  10. package/scripts/hooks-system/application/services/installation/McpConfigurator.js +9 -205
  11. package/scripts/hooks-system/application/services/installation/mcp/McpGlobalConfigCleaner.js +49 -0
  12. package/scripts/hooks-system/application/services/installation/mcp/McpProjectConfigWriter.js +59 -0
  13. package/scripts/hooks-system/application/services/installation/mcp/McpServerConfigBuilder.js +103 -0
  14. package/scripts/hooks-system/application/services/monitoring/EvidenceMonitor.js +146 -5
  15. package/scripts/hooks-system/infrastructure/ast/ast-core.js +1 -13
  16. package/scripts/hooks-system/infrastructure/ast/ast-intelligence.js +3 -2
  17. package/scripts/hooks-system/infrastructure/ast/backend/ast-backend.js +17 -9
  18. package/scripts/hooks-system/infrastructure/ast/backend/detectors/god-class-detector.js +2 -1
  19. package/scripts/hooks-system/infrastructure/ast/ios/analyzers/iOSASTIntelligentAnalyzer.js +137 -27
  20. package/scripts/hooks-system/infrastructure/ast/ios/analyzers/iOSCICDChecks.js +385 -0
  21. package/scripts/hooks-system/infrastructure/ast/ios/analyzers/iOSCICDRules.js +38 -408
  22. package/scripts/hooks-system/infrastructure/ast/ios/analyzers/iOSEnterpriseAnalyzer.js +397 -34
  23. package/scripts/hooks-system/infrastructure/ast/ios/analyzers/iOSSPMChecks.js +408 -0
  24. package/scripts/hooks-system/infrastructure/ast/ios/analyzers/iOSSPMRules.js +36 -442
  25. package/scripts/hooks-system/infrastructure/ast/ios/parsers/SourceKittenExtractor.js +146 -0
  26. package/scripts/hooks-system/infrastructure/ast/ios/parsers/SourceKittenParser.js +22 -190
  27. package/scripts/hooks-system/infrastructure/ast/ios/parsers/SourceKittenRunner.js +62 -0
  28. package/scripts/hooks-system/infrastructure/mcp/ast-intelligence-automation.js +42 -47
  29. package/scripts/hooks-system/infrastructure/orchestration/__tests__/intelligent-audit.spec.js +0 -16
  30. package/scripts/hooks-system/infrastructure/orchestration/intelligent-audit.js +14 -25
  31. package/scripts/hooks-system/infrastructure/shell/gitflow/gitflow-enforcer.sh +0 -10
  32. package/scripts/hooks-system/application/services/installation/HookAssetsInstaller.js +0 -0
  33. package/scripts/hooks-system/application/services/monitoring/EvidenceRefreshRunner.js +0 -161
  34. package/scripts/hooks-system/infrastructure/ast/ios/analyzers/StagedSwiftFilePreparer.js +0 -59
  35. package/scripts/hooks-system/infrastructure/ast/ios/analyzers/SwiftAstRunner.js +0 -51
  36. package/scripts/hooks-system/infrastructure/ast/ios/analyzers/SwiftToolchainResolver.js +0 -57
  37. package/scripts/hooks-system/infrastructure/ast/ios/analyzers/iOSAstAnalysisOrchestrator.js +0 -32
  38. package/scripts/hooks-system/infrastructure/ast/ios/analyzers/iOSEnterpriseChecks.js +0 -350
@@ -0,0 +1,385 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const glob = require('glob');
4
+
5
+ function checkFastfileExists(ctx) {
6
+ const fastfilePath = path.join(ctx.projectRoot, 'fastlane/Fastfile');
7
+ if (!fs.existsSync(fastfilePath)) {
8
+ ctx.pushFinding(ctx.findings, {
9
+ ruleId: 'ios.cicd.missing_fastfile',
10
+ severity: 'medium',
11
+ message: 'Proyecto iOS sin Fastfile. Fastlane automatiza builds, tests y deployments.',
12
+ filePath: 'PROJECT_ROOT',
13
+ line: 1,
14
+ suggestion: `Inicializar Fastlane:
15
+
16
+ fastlane init
17
+
18
+ Esto crea:
19
+ - fastlane/Fastfile
20
+ - fastlane/Appfile
21
+ - fastlane/Matchfile`
22
+ });
23
+ return;
24
+ }
25
+ checkFastfileLanes(ctx, fastfilePath);
26
+ }
27
+
28
+ function checkFastfileLanes(ctx, fastfilePath) {
29
+ const content = fs.readFileSync(fastfilePath, 'utf-8');
30
+ const requiredLanes = ['test', 'beta', 'release'];
31
+ const existingLanes = content.match(/lane\s+:(\w+)/g)?.map(l => l.match(/:(\w+)/)?.[1]) || [];
32
+ const missingLanes = requiredLanes.filter(lane => !existingLanes.includes(lane));
33
+
34
+ if (missingLanes.length > 0) {
35
+ ctx.pushFinding(ctx.findings, {
36
+ ruleId: 'ios.cicd.fastfile_missing_lanes',
37
+ severity: 'medium',
38
+ message: `Fastfile sin lanes esenciales: ${missingLanes.join(', ')}`,
39
+ filePath: fastfilePath,
40
+ line: 1,
41
+ suggestion: `Añadir lanes:
42
+
43
+ lane :test do
44
+ scan
45
+ end
46
+
47
+ lane :beta do
48
+ build_app
49
+ upload_to_testflight
50
+ end
51
+
52
+ lane :release do
53
+ build_app
54
+ upload_to_app_store
55
+ end`
56
+ });
57
+ }
58
+
59
+ if (!content.includes('increment_build_number') && !content.includes('increment_version_number')) {
60
+ ctx.pushFinding(ctx.findings, {
61
+ ruleId: 'ios.cicd.missing_version_increment',
62
+ severity: 'medium',
63
+ message: 'Fastfile sin incremento automático de versión/build.',
64
+ filePath: fastfilePath,
65
+ line: 1
66
+ });
67
+ }
68
+ }
69
+
70
+ function checkGitHubActionsWorkflow(ctx) {
71
+ const workflowPath = path.join(ctx.projectRoot, '.github/workflows');
72
+
73
+ if (!fs.existsSync(workflowPath)) {
74
+ ctx.pushFinding(ctx.findings, {
75
+ ruleId: 'ios.cicd.missing_github_actions',
76
+ severity: 'low',
77
+ message: 'Proyecto sin GitHub Actions workflows. Automatizar CI/CD.',
78
+ filePath: 'PROJECT_ROOT',
79
+ line: 1,
80
+ suggestion: 'Crear .github/workflows/ios-ci.yml para tests automáticos'
81
+ });
82
+ return;
83
+ }
84
+
85
+ const workflows = glob.sync('*.yml', { cwd: workflowPath, absolute: true });
86
+ const iosWorkflows = workflows.filter(w => {
87
+ const content = fs.readFileSync(w, 'utf-8');
88
+ return content.includes('macos') || content.includes('ios') || content.includes('xcodebuild');
89
+ });
90
+
91
+ if (iosWorkflows.length === 0) {
92
+ ctx.pushFinding(ctx.findings, {
93
+ ruleId: 'ios.cicd.no_ios_workflow',
94
+ severity: 'medium',
95
+ message: 'GitHub Actions sin workflow de iOS.',
96
+ filePath: '.github/workflows/',
97
+ line: 1
98
+ });
99
+ return;
100
+ }
101
+
102
+ iosWorkflows.forEach(workflow => {
103
+ const content = fs.readFileSync(workflow, 'utf-8');
104
+
105
+ if (!content.includes('xcodebuild test')) {
106
+ ctx.pushFinding(ctx.findings, {
107
+ ruleId: 'ios.cicd.workflow_missing_tests',
108
+ severity: 'high',
109
+ message: 'Workflow de iOS sin tests automáticos.',
110
+ filePath: workflow,
111
+ line: 1
112
+ });
113
+ }
114
+
115
+ if (!content.includes('fastlane')) {
116
+ ctx.pushFinding(ctx.findings, {
117
+ ruleId: 'ios.cicd.workflow_without_fastlane',
118
+ severity: 'low',
119
+ message: 'Workflow sin Fastlane. Considerar para simplificar pipeline.',
120
+ filePath: workflow,
121
+ line: 1
122
+ });
123
+ }
124
+ });
125
+ }
126
+
127
+ function checkTestFlightConfiguration(ctx) {
128
+ const fastfilePath = path.join(ctx.projectRoot, 'fastlane/Fastfile');
129
+ if (!fs.existsSync(fastfilePath)) return;
130
+
131
+ const content = fs.readFileSync(fastfilePath, 'utf-8');
132
+ if (content.includes('beta') && !content.includes('upload_to_testflight')) {
133
+ ctx.pushFinding(ctx.findings, {
134
+ ruleId: 'ios.cicd.beta_without_testflight',
135
+ severity: 'medium',
136
+ message: 'Lane beta sin upload_to_testflight. Automatizar distribución.',
137
+ filePath: fastfilePath,
138
+ line: 1
139
+ });
140
+ }
141
+
142
+ if (content.includes('upload_to_testflight') && !content.includes('changelog')) {
143
+ ctx.pushFinding(ctx.findings, {
144
+ ruleId: 'ios.cicd.testflight_without_changelog',
145
+ severity: 'low',
146
+ message: 'TestFlight sin changelog. Añadir notas de release.',
147
+ filePath: fastfilePath,
148
+ line: 1
149
+ });
150
+ }
151
+ }
152
+
153
+ function checkBuildConfiguration(ctx) {
154
+ const projectFiles = glob.sync('**/*.xcodeproj/project.pbxproj', {
155
+ cwd: ctx.projectRoot,
156
+ absolute: true
157
+ });
158
+ if (projectFiles.length === 0) return;
159
+
160
+ projectFiles.forEach(projectFile => {
161
+ const content = fs.readFileSync(projectFile, 'utf-8');
162
+ const configurations = content.match(/buildConfiguration\s*=\s*(\w+)/g) || [];
163
+ const hasDebug = configurations.some(c => c.includes('Debug'));
164
+ const hasRelease = configurations.some(c => c.includes('Release'));
165
+ const hasStaging = configurations.some(c => c.includes('Staging'));
166
+
167
+ if (!hasStaging && (hasDebug && hasRelease)) {
168
+ ctx.pushFinding(ctx.findings, {
169
+ ruleId: 'ios.cicd.missing_staging_config',
170
+ severity: 'low',
171
+ message: 'Sin configuración Staging. Útil para testing pre-production.',
172
+ filePath: projectFile,
173
+ line: 1
174
+ });
175
+ }
176
+ });
177
+ }
178
+
179
+ function checkCertificateManagement(ctx) {
180
+ const matchfilePath = path.join(ctx.projectRoot, 'fastlane/Matchfile');
181
+ if (fs.existsSync(matchfilePath)) return;
182
+
183
+ const fastfilePath = path.join(ctx.projectRoot, 'fastlane/Fastfile');
184
+ if (fs.existsSync(fastfilePath)) {
185
+ ctx.pushFinding(ctx.findings, {
186
+ ruleId: 'ios.cicd.missing_match_config',
187
+ severity: 'medium',
188
+ message: 'Fastlane sin Match para gestión de certificados.',
189
+ filePath: 'fastlane/',
190
+ line: 1,
191
+ suggestion: 'fastlane match init para gestionar certificados en equipo'
192
+ });
193
+ }
194
+ }
195
+
196
+ function checkCodeSigningConfiguration(ctx) {
197
+ const projectFiles = glob.sync('**/*.xcodeproj/project.pbxproj', {
198
+ cwd: ctx.projectRoot,
199
+ absolute: true
200
+ });
201
+
202
+ projectFiles.forEach(projectFile => {
203
+ const content = fs.readFileSync(projectFile, 'utf-8');
204
+ if (content.includes('CODE_SIGN_STYLE = Manual')) {
205
+ ctx.pushFinding(ctx.findings, {
206
+ ruleId: 'ios.cicd.manual_code_signing',
207
+ severity: 'low',
208
+ message: 'Code signing manual. Considerar Automatic o Match para CI/CD.',
209
+ filePath: projectFile,
210
+ line: 1
211
+ });
212
+ }
213
+ });
214
+ }
215
+
216
+ function checkAutomatedTesting(ctx) {
217
+ const fastfilePath = path.join(ctx.projectRoot, 'fastlane/Fastfile');
218
+ if (!fs.existsSync(fastfilePath)) return;
219
+
220
+ const content = fs.readFileSync(fastfilePath, 'utf-8');
221
+ if (!content.includes('scan') && !content.includes('run_tests')) {
222
+ ctx.pushFinding(ctx.findings, {
223
+ ruleId: 'ios.cicd.no_automated_tests',
224
+ severity: 'high',
225
+ message: 'Fastlane sin tests automatizados. Añadir scan action.',
226
+ filePath: fastfilePath,
227
+ line: 1,
228
+ suggestion: `lane :test do
229
+ scan(scheme: "MyApp")
230
+ end`
231
+ });
232
+ }
233
+ }
234
+
235
+ function checkVersionBumping(ctx) {
236
+ const fastfilePath = path.join(ctx.projectRoot, 'fastlane/Fastfile');
237
+ if (!fs.existsSync(fastfilePath)) return;
238
+
239
+ const content = fs.readFileSync(fastfilePath, 'utf-8');
240
+ if (content.includes('upload_to') && !content.includes('increment_build_number')) {
241
+ ctx.pushFinding(ctx.findings, {
242
+ ruleId: 'ios.cicd.missing_build_increment',
243
+ severity: 'medium',
244
+ message: 'Deployment sin incremento automático de build number.',
245
+ filePath: fastfilePath,
246
+ line: 1
247
+ });
248
+ }
249
+ }
250
+
251
+ function checkReleaseNotes(ctx) {
252
+ const changelogPath = path.join(ctx.projectRoot, 'CHANGELOG.md');
253
+ const fastfilePath = path.join(ctx.projectRoot, 'fastlane/Fastfile');
254
+ if (!fs.existsSync(fastfilePath) || fs.existsSync(changelogPath)) return;
255
+
256
+ ctx.pushFinding(ctx.findings, {
257
+ ruleId: 'ios.cicd.missing_changelog',
258
+ severity: 'low',
259
+ message: 'Proyecto sin CHANGELOG.md. Documentar cambios para releases.',
260
+ filePath: 'PROJECT_ROOT',
261
+ line: 1
262
+ });
263
+ }
264
+
265
+ function checkSlackNotifications(ctx) {
266
+ const fastfilePath = path.join(ctx.projectRoot, 'fastlane/Fastfile');
267
+ if (!fs.existsSync(fastfilePath)) return;
268
+
269
+ const content = fs.readFileSync(fastfilePath, 'utf-8');
270
+ if (content.includes('upload_to') && !content.includes('slack')) {
271
+ ctx.pushFinding(ctx.findings, {
272
+ ruleId: 'ios.cicd.missing_notifications',
273
+ severity: 'low',
274
+ message: 'Deployment sin notificaciones. Añadir Slack para avisar al equipo.',
275
+ filePath: fastfilePath,
276
+ line: 1
277
+ });
278
+ }
279
+ }
280
+
281
+ function checkMatchConfiguration(ctx) {
282
+ const matchfilePath = path.join(ctx.projectRoot, 'fastlane/Matchfile');
283
+ if (!fs.existsSync(matchfilePath)) return;
284
+
285
+ const content = fs.readFileSync(matchfilePath, 'utf-8');
286
+ if (!content.includes('git_url')) {
287
+ ctx.pushFinding(ctx.findings, {
288
+ ruleId: 'ios.cicd.match_missing_git_url',
289
+ severity: 'high',
290
+ message: 'Matchfile sin git_url. Match requiere repositorio para certificados.',
291
+ filePath: matchfilePath,
292
+ line: 1
293
+ });
294
+ }
295
+ }
296
+
297
+ function checkGymConfiguration(ctx) {
298
+ const gymfilePath = path.join(ctx.projectRoot, 'fastlane/Gymfile');
299
+ const fastfilePath = path.join(ctx.projectRoot, 'fastlane/Fastfile');
300
+ if (!fs.existsSync(fastfilePath) || fs.existsSync(gymfilePath)) return;
301
+
302
+ const content = fs.readFileSync(fastfilePath, 'utf-8');
303
+ if (content.includes('build_app') || content.includes('gym')) {
304
+ ctx.pushFinding(ctx.findings, {
305
+ ruleId: 'ios.cicd.missing_gymfile',
306
+ severity: 'low',
307
+ message: 'build_app sin Gymfile. Considerar para centralizar configuración de build.',
308
+ filePath: 'fastlane/',
309
+ line: 1
310
+ });
311
+ }
312
+ }
313
+
314
+ function checkScanConfiguration(ctx) {
315
+ const fastfilePath = path.join(ctx.projectRoot, 'fastlane/Fastfile');
316
+ if (!fs.existsSync(fastfilePath)) return;
317
+
318
+ const content = fs.readFileSync(fastfilePath, 'utf-8');
319
+ if (content.includes('scan') && !content.includes('code_coverage')) {
320
+ ctx.pushFinding(ctx.findings, {
321
+ ruleId: 'ios.cicd.scan_without_coverage',
322
+ severity: 'low',
323
+ message: 'scan sin code_coverage: true. Activar para métricas.',
324
+ filePath: fastfilePath,
325
+ line: 1,
326
+ suggestion: 'scan(code_coverage: true, scheme: "MyApp")'
327
+ });
328
+ }
329
+ }
330
+
331
+ function checkPilotConfiguration(ctx) {
332
+ const fastfilePath = path.join(ctx.projectRoot, 'fastlane/Fastfile');
333
+ if (!fs.existsSync(fastfilePath)) return;
334
+
335
+ const content = fs.readFileSync(fastfilePath, 'utf-8');
336
+ if (!content.includes('pilot') && !content.includes('upload_to_testflight')) return;
337
+
338
+ if (!content.includes('changelog') && !content.includes('whats_new')) {
339
+ ctx.pushFinding(ctx.findings, {
340
+ ruleId: 'ios.cicd.pilot_missing_changelog',
341
+ severity: 'low',
342
+ message: 'TestFlight upload sin changelog/whats_new.',
343
+ filePath: fastfilePath,
344
+ line: 1
345
+ });
346
+ }
347
+ }
348
+
349
+ function checkAppStoreMetadata(ctx) {
350
+ const metadataPath = path.join(ctx.projectRoot, 'fastlane/metadata');
351
+ if (fs.existsSync(metadataPath)) return;
352
+
353
+ const fastfilePath = path.join(ctx.projectRoot, 'fastlane/Fastfile');
354
+ if (!fs.existsSync(fastfilePath)) return;
355
+
356
+ const content = fs.readFileSync(fastfilePath, 'utf-8');
357
+ if (content.includes('upload_to_app_store') || content.includes('deliver')) {
358
+ ctx.pushFinding(ctx.findings, {
359
+ ruleId: 'ios.cicd.missing_metadata',
360
+ severity: 'low',
361
+ message: 'Upload a App Store sin metadata/ folder. Versionar descripciones y screenshots.',
362
+ filePath: 'fastlane/',
363
+ line: 1,
364
+ suggestion: 'fastlane deliver init para crear estructura metadata/'
365
+ });
366
+ }
367
+ }
368
+
369
+ module.exports = {
370
+ checkFastfileExists,
371
+ checkGitHubActionsWorkflow,
372
+ checkTestFlightConfiguration,
373
+ checkBuildConfiguration,
374
+ checkCertificateManagement,
375
+ checkCodeSigningConfiguration,
376
+ checkAutomatedTesting,
377
+ checkVersionBumping,
378
+ checkReleaseNotes,
379
+ checkSlackNotifications,
380
+ checkMatchConfiguration,
381
+ checkGymConfiguration,
382
+ checkScanConfiguration,
383
+ checkPilotConfiguration,
384
+ checkAppStoreMetadata,
385
+ };