pumuki-ast-hooks 5.5.50 → 5.5.51
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/package.json +1 -1
- package/scripts/hooks-system/.audit_tmp/hook-metrics.jsonl +48 -0
- package/scripts/hooks-system/application/services/installation/HookAssetsInstaller.js +0 -0
- package/scripts/hooks-system/application/services/installation/McpConfigurator.js +84 -18
- package/scripts/hooks-system/application/services/monitoring/EvidenceMonitor.js +5 -146
- package/scripts/hooks-system/application/services/monitoring/EvidenceRefreshRunner.js +161 -0
- package/scripts/hooks-system/infrastructure/ast/ios/analyzers/StagedSwiftFilePreparer.js +59 -0
- package/scripts/hooks-system/infrastructure/ast/ios/analyzers/SwiftAstRunner.js +51 -0
- package/scripts/hooks-system/infrastructure/ast/ios/analyzers/SwiftToolchainResolver.js +57 -0
- package/scripts/hooks-system/infrastructure/ast/ios/analyzers/iOSASTIntelligentAnalyzer.js +27 -137
- package/scripts/hooks-system/infrastructure/ast/ios/analyzers/iOSAstAnalysisOrchestrator.js +32 -0
- package/scripts/hooks-system/infrastructure/mcp/ast-intelligence-automation.js +407 -5
- package/scripts/hooks-system/infrastructure/shell/gitflow/gitflow-enforcer.sh +21 -67
|
@@ -576,9 +576,293 @@ function checkBranchChangesCoherence(branchName, uncommittedChanges) {
|
|
|
576
576
|
return { isCoherent: true, expectedScope, detectedScope: dominantScope, reason: 'Changes match branch scope' };
|
|
577
577
|
}
|
|
578
578
|
|
|
579
|
+
/**
|
|
580
|
+
* Load platform rules from .cursor/rules or .windsurf/rules
|
|
581
|
+
* Returns the content of the rules file for the detected platform
|
|
582
|
+
*/
|
|
583
|
+
async function loadPlatformRules(platforms) {
|
|
584
|
+
const DynamicRulesLoader = require('../../application/services/DynamicRulesLoader');
|
|
585
|
+
const loader = new DynamicRulesLoader();
|
|
586
|
+
const rules = {};
|
|
587
|
+
const criticalRules = [];
|
|
588
|
+
|
|
589
|
+
for (const platform of platforms) {
|
|
590
|
+
try {
|
|
591
|
+
const content = await loader.loadRule(`rules${platform}.mdc`);
|
|
592
|
+
if (content) {
|
|
593
|
+
rules[platform] = content;
|
|
594
|
+
const criticalPatterns = extractCriticalPatterns(content, platform);
|
|
595
|
+
criticalRules.push(...criticalPatterns);
|
|
596
|
+
}
|
|
597
|
+
} catch (error) {
|
|
598
|
+
if (process.env.DEBUG) {
|
|
599
|
+
process.stderr.write(`[MCP] Failed to load rules for ${platform}: ${error.message}\n`);
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
try {
|
|
605
|
+
const goldContent = await loader.loadRule('rulesgold.mdc');
|
|
606
|
+
if (goldContent) {
|
|
607
|
+
rules.gold = goldContent;
|
|
608
|
+
const goldPatterns = extractCriticalPatterns(goldContent, 'gold');
|
|
609
|
+
criticalRules.push(...goldPatterns);
|
|
610
|
+
}
|
|
611
|
+
} catch (error) {
|
|
612
|
+
if (process.env.DEBUG) {
|
|
613
|
+
process.stderr.write(`[MCP] Failed to load gold rules: ${error.message}\n`);
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
return { rules, criticalRules };
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
/**
|
|
621
|
+
* Extract critical patterns from rules content that AI MUST follow
|
|
622
|
+
*/
|
|
623
|
+
function extractCriticalPatterns(content, platform) {
|
|
624
|
+
const patterns = [];
|
|
625
|
+
if (!content) return patterns;
|
|
626
|
+
|
|
627
|
+
const lines = content.split('\n');
|
|
628
|
+
for (const line of lines) {
|
|
629
|
+
if (line.includes('❌') || line.includes('NUNCA') || line.includes('PROHIBIDO') || line.includes('NO ')) {
|
|
630
|
+
patterns.push({ platform, rule: line.trim(), severity: 'CRITICAL' });
|
|
631
|
+
}
|
|
632
|
+
if (line.includes('✅') && (line.includes('OBLIGATORIO') || line.includes('SIEMPRE'))) {
|
|
633
|
+
patterns.push({ platform, rule: line.trim(), severity: 'MANDATORY' });
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
if (platform === 'ios') {
|
|
638
|
+
// PROHIBICIONES CRÍTICAS iOS
|
|
639
|
+
patterns.push({ platform: 'ios', rule: '❌ NUNCA usar GCD (DispatchQueue.main.async, DispatchQueue.global) - usar Swift Concurrency (async/await, Task, actor, @MainActor)', severity: 'CRITICAL' });
|
|
640
|
+
patterns.push({ platform: 'ios', rule: '❌ NUNCA usar completion handlers/@escaping callbacks - usar async/await', severity: 'CRITICAL' });
|
|
641
|
+
patterns.push({ platform: 'ios', rule: '❌ NUNCA dejar catch vacíos - siempre gestionar errores (log/rethrow/wrap)', severity: 'CRITICAL' });
|
|
642
|
+
patterns.push({ platform: 'ios', rule: '❌ NUNCA mezclar operaciones de escritura (commands) con lecturas (queries) en el mismo flujo/servicio - aplicar CQRS', severity: 'CRITICAL' });
|
|
643
|
+
patterns.push({ platform: 'ios', rule: '❌ NUNCA usar Singleton - usar Inyección de Dependencias (DI por init/protocols)', severity: 'CRITICAL' });
|
|
644
|
+
patterns.push({ platform: 'ios', rule: '❌ NUNCA usar force unwrap (!) - usar guard let/if let/?? (excepción: IBOutlets)', severity: 'CRITICAL' });
|
|
645
|
+
patterns.push({ platform: 'ios', rule: '❌ NUNCA usar librerías de terceros (Alamofire, Swinject, Quick/Nimble, etc.) - usar APIs nativas (URLSession, DI manual, Swift Testing)', severity: 'CRITICAL' });
|
|
646
|
+
patterns.push({ platform: 'ios', rule: '❌ NUNCA añadir comentarios en el código - nombres autodescriptivos', severity: 'CRITICAL' });
|
|
647
|
+
patterns.push({ platform: 'ios', rule: '❌ NUNCA usar prints/logs ad-hoc - usar Logger del framework os', severity: 'CRITICAL' });
|
|
648
|
+
patterns.push({ platform: 'ios', rule: '❌ NUNCA usar AnyView - afecta performance, usar @ViewBuilder o generics', severity: 'CRITICAL' });
|
|
649
|
+
patterns.push({ platform: 'ios', rule: '❌ NUNCA usar ObservableObject - usar @Observable (iOS 17+)', severity: 'CRITICAL' });
|
|
650
|
+
patterns.push({ platform: 'ios', rule: '❌ NUNCA usar Storyboards/XIBs - usar SwiftUI o Programmatic UI', severity: 'CRITICAL' });
|
|
651
|
+
patterns.push({ platform: 'ios', rule: '❌ NUNCA usar CocoaPods/Carthage - usar Swift Package Manager', severity: 'CRITICAL' });
|
|
652
|
+
patterns.push({ platform: 'ios', rule: '❌ NUNCA usar JSONSerialization - usar Codable', severity: 'CRITICAL' });
|
|
653
|
+
patterns.push({ platform: 'ios', rule: '❌ NUNCA usar OperationQueue para async - usar Task/TaskGroup', severity: 'CRITICAL' });
|
|
654
|
+
patterns.push({ platform: 'ios', rule: '❌ NUNCA usar any (type erasure) - usar generics con protocolos de frontera', severity: 'CRITICAL' });
|
|
655
|
+
patterns.push({ platform: 'ios', rule: '❌ NUNCA usar Localizable.strings - usar String Catalogs (.xcstrings)', severity: 'CRITICAL' });
|
|
656
|
+
patterns.push({ platform: 'ios', rule: '❌ NUNCA ignorar warnings - warnings = errores futuros', severity: 'CRITICAL' });
|
|
657
|
+
patterns.push({ platform: 'ios', rule: '❌ NUNCA crear Massive View Controllers (>300 líneas) - separar lógica en ViewModels', severity: 'CRITICAL' });
|
|
658
|
+
patterns.push({ platform: 'ios', rule: '❌ NUNCA crear retain cycles - usar [weak self] en closures', severity: 'CRITICAL' });
|
|
659
|
+
|
|
660
|
+
// OBLIGATORIOS iOS
|
|
661
|
+
patterns.push({ platform: 'ios', rule: '✅ OBLIGATORIO usar Swift 6.2 con Strict Concurrency Checking en Complete', severity: 'MANDATORY' });
|
|
662
|
+
patterns.push({ platform: 'ios', rule: '✅ OBLIGATORIO usar async/await para TODAS las operaciones asíncronas', severity: 'MANDATORY' });
|
|
663
|
+
patterns.push({ platform: 'ios', rule: '✅ OBLIGATORIO usar SwiftUI (UIKit solo si estrictamente necesario)', severity: 'MANDATORY' });
|
|
664
|
+
patterns.push({ platform: 'ios', rule: '✅ OBLIGATORIO usar @Observable (iOS 17+) con @Bindable para bindings', severity: 'MANDATORY' });
|
|
665
|
+
patterns.push({ platform: 'ios', rule: '✅ OBLIGATORIO usar NavigationStack + NavigationPath para navegación', severity: 'MANDATORY' });
|
|
666
|
+
patterns.push({ platform: 'ios', rule: '✅ OBLIGATORIO usar guard/early returns - evitar pyramid of doom', severity: 'MANDATORY' });
|
|
667
|
+
patterns.push({ platform: 'ios', rule: '✅ OBLIGATORIO seguir Clean Architecture (Domain → Application → Infrastructure → Presentation)', severity: 'MANDATORY' });
|
|
668
|
+
patterns.push({ platform: 'ios', rule: '✅ OBLIGATORIO aplicar CQRS (Command Query Responsibility Segregation): separar comandos (write) de consultas (read)', severity: 'MANDATORY' });
|
|
669
|
+
patterns.push({ platform: 'ios', rule: '✅ OBLIGATORIO verificar SOLID (SRP, OCP, LSP, ISP, DIP)', severity: 'MANDATORY' });
|
|
670
|
+
patterns.push({ platform: 'ios', rule: '✅ OBLIGATORIO nombres autodescriptivos en inglés', severity: 'MANDATORY' });
|
|
671
|
+
patterns.push({ platform: 'ios', rule: '✅ OBLIGATORIO comprobar que compila (Xcode build) ANTES de sugerir', severity: 'MANDATORY' });
|
|
672
|
+
patterns.push({ platform: 'ios', rule: '✅ OBLIGATORIO usar Sendable conformance para tipos thread-safe', severity: 'MANDATORY' });
|
|
673
|
+
patterns.push({ platform: 'ios', rule: '✅ OBLIGATORIO usar actor para estado compartido thread-safe', severity: 'MANDATORY' });
|
|
674
|
+
patterns.push({ platform: 'ios', rule: '✅ OBLIGATORIO usar @MainActor para código UI', severity: 'MANDATORY' });
|
|
675
|
+
patterns.push({ platform: 'ios', rule: '✅ OBLIGATORIO usar Task {} para lanzar contextos asíncronos desde código síncrono', severity: 'MANDATORY' });
|
|
676
|
+
patterns.push({ platform: 'ios', rule: '✅ OBLIGATORIO usar Keychain nativo para datos sensibles (NO UserDefaults)', severity: 'MANDATORY' });
|
|
677
|
+
patterns.push({ platform: 'ios', rule: '✅ OBLIGATORIO usar SwiftData (iOS 17+) para persistencia (CoreData solo legacy)', severity: 'MANDATORY' });
|
|
678
|
+
patterns.push({ platform: 'ios', rule: '✅ OBLIGATORIO usar Swift Testing framework para tests (XCTest solo legacy)', severity: 'MANDATORY' });
|
|
679
|
+
patterns.push({ platform: 'ios', rule: '✅ OBLIGATORIO usar makeSUT pattern en tests', severity: 'MANDATORY' });
|
|
680
|
+
patterns.push({ platform: 'ios', rule: '✅ OBLIGATORIO usar trackForMemoryLeaks helper en tests', severity: 'MANDATORY' });
|
|
681
|
+
patterns.push({ platform: 'ios', rule: '✅ OBLIGATORIO usar spies en vez de mocks/stubs', severity: 'MANDATORY' });
|
|
682
|
+
patterns.push({ platform: 'ios', rule: '✅ OBLIGATORIO usar protocols para testability (inyectar protocols, no tipos concretos)', severity: 'MANDATORY' });
|
|
683
|
+
patterns.push({ platform: 'ios', rule: '✅ OBLIGATORIO usar struct por defecto, class solo cuando necesites identity/herencia', severity: 'MANDATORY' });
|
|
684
|
+
patterns.push({ platform: 'ios', rule: '✅ OBLIGATORIO usar let > var (inmutabilidad por defecto)', severity: 'MANDATORY' });
|
|
685
|
+
patterns.push({ platform: 'ios', rule: '✅ OBLIGATORIO cero warnings en el proyecto', severity: 'MANDATORY' });
|
|
686
|
+
patterns.push({ platform: 'ios', rule: '✅ OBLIGATORIO seguir flujo BDD → TDD (Feature files → Specs → Implementación)', severity: 'MANDATORY' });
|
|
687
|
+
patterns.push({ platform: 'ios', rule: '✅ OBLIGATORIO en producción todo real contra APIs/persistencia (cero mocks/spies)', severity: 'MANDATORY' });
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
if (platform === 'android') {
|
|
691
|
+
// PROHIBICIONES CRÍTICAS Android
|
|
692
|
+
patterns.push({ platform: 'android', rule: '❌ NUNCA usar Singleton - usar Hilt para Inyección de Dependencias', severity: 'CRITICAL' });
|
|
693
|
+
patterns.push({ platform: 'android', rule: '❌ NUNCA usar XML layouts - usar Jetpack Compose', severity: 'CRITICAL' });
|
|
694
|
+
patterns.push({ platform: 'android', rule: '❌ NUNCA usar Java en código nuevo - usar Kotlin 100%', severity: 'CRITICAL' });
|
|
695
|
+
patterns.push({ platform: 'android', rule: '❌ NUNCA usar LiveData - usar StateFlow/SharedFlow', severity: 'CRITICAL' });
|
|
696
|
+
patterns.push({ platform: 'android', rule: '❌ NUNCA dejar catch vacíos - siempre gestionar errores', severity: 'CRITICAL' });
|
|
697
|
+
patterns.push({ platform: 'android', rule: '❌ NUNCA mezclar operaciones de escritura (commands) con lecturas (queries) en el mismo caso de uso/repository - aplicar CQRS', severity: 'CRITICAL' });
|
|
698
|
+
patterns.push({ platform: 'android', rule: '❌ NUNCA añadir comentarios en el código', severity: 'CRITICAL' });
|
|
699
|
+
patterns.push({ platform: 'android', rule: '❌ NUNCA usar force unwrap (!!) - usar ?, ?:, let, requireNotNull', severity: 'CRITICAL' });
|
|
700
|
+
patterns.push({ platform: 'android', rule: '❌ NUNCA usar AsyncTask (deprecated) - usar Coroutines', severity: 'CRITICAL' });
|
|
701
|
+
patterns.push({ platform: 'android', rule: '❌ NUNCA usar RxJava en código nuevo - usar Flow', severity: 'CRITICAL' });
|
|
702
|
+
patterns.push({ platform: 'android', rule: '❌ NUNCA usar findViewById - usar Compose o View Binding', severity: 'CRITICAL' });
|
|
703
|
+
patterns.push({ platform: 'android', rule: '❌ NUNCA usar Context leaks - no referencias a Activity en objetos long-lived', severity: 'CRITICAL' });
|
|
704
|
+
patterns.push({ platform: 'android', rule: '❌ NUNCA usar God Activities - Single Activity + Composables', severity: 'CRITICAL' });
|
|
705
|
+
patterns.push({ platform: 'android', rule: '❌ NUNCA hardcodear strings - usar strings.xml', severity: 'CRITICAL' });
|
|
706
|
+
patterns.push({ platform: 'android', rule: '❌ NUNCA usar callbacks para async - usar suspend functions', severity: 'CRITICAL' });
|
|
707
|
+
|
|
708
|
+
// OBLIGATORIOS Android
|
|
709
|
+
patterns.push({ platform: 'android', rule: '✅ OBLIGATORIO usar Jetpack Compose + Material 3', severity: 'MANDATORY' });
|
|
710
|
+
patterns.push({ platform: 'android', rule: '✅ OBLIGATORIO usar Hilt para DI (@HiltAndroidApp, @AndroidEntryPoint, @Inject)', severity: 'MANDATORY' });
|
|
711
|
+
patterns.push({ platform: 'android', rule: '✅ OBLIGATORIO usar Kotlin Coroutines + Flow para async', severity: 'MANDATORY' });
|
|
712
|
+
patterns.push({ platform: 'android', rule: '✅ OBLIGATORIO usar StateFlow para exponer estado del ViewModel', severity: 'MANDATORY' });
|
|
713
|
+
patterns.push({ platform: 'android', rule: '✅ OBLIGATORIO usar sealed classes para estados (Success, Error, Loading)', severity: 'MANDATORY' });
|
|
714
|
+
patterns.push({ platform: 'android', rule: '✅ OBLIGATORIO seguir Clean Architecture (Domain → Data → Presentation)', severity: 'MANDATORY' });
|
|
715
|
+
patterns.push({ platform: 'android', rule: '✅ OBLIGATORIO aplicar CQRS (Command Query Responsibility Segregation): separar comandos (write) de consultas (read)', severity: 'MANDATORY' });
|
|
716
|
+
patterns.push({ platform: 'android', rule: '✅ OBLIGATORIO verificar SOLID', severity: 'MANDATORY' });
|
|
717
|
+
patterns.push({ platform: 'android', rule: '✅ OBLIGATORIO usar MVVM + Single Activity', severity: 'MANDATORY' });
|
|
718
|
+
patterns.push({ platform: 'android', rule: '✅ OBLIGATORIO usar Navigation Compose para navegación', severity: 'MANDATORY' });
|
|
719
|
+
patterns.push({ platform: 'android', rule: '✅ OBLIGATORIO usar Room para persistencia local', severity: 'MANDATORY' });
|
|
720
|
+
patterns.push({ platform: 'android', rule: '✅ OBLIGATORIO usar Retrofit + Moshi para networking', severity: 'MANDATORY' });
|
|
721
|
+
patterns.push({ platform: 'android', rule: '✅ OBLIGATORIO usar Coil para carga de imágenes', severity: 'MANDATORY' });
|
|
722
|
+
patterns.push({ platform: 'android', rule: '✅ OBLIGATORIO usar Kotlin DSL (build.gradle.kts)', severity: 'MANDATORY' });
|
|
723
|
+
patterns.push({ platform: 'android', rule: '✅ OBLIGATORIO usar Version Catalogs (libs.versions.toml)', severity: 'MANDATORY' });
|
|
724
|
+
patterns.push({ platform: 'android', rule: '✅ OBLIGATORIO usar JUnit5 + MockK para testing', severity: 'MANDATORY' });
|
|
725
|
+
patterns.push({ platform: 'android', rule: '✅ OBLIGATORIO usar Timber para logging (solo en DEBUG)', severity: 'MANDATORY' });
|
|
726
|
+
patterns.push({ platform: 'android', rule: '✅ OBLIGATORIO usar EncryptedSharedPreferences para datos sensibles', severity: 'MANDATORY' });
|
|
727
|
+
patterns.push({ platform: 'android', rule: '✅ OBLIGATORIO nombres autodescriptivos en inglés', severity: 'MANDATORY' });
|
|
728
|
+
patterns.push({ platform: 'android', rule: '✅ OBLIGATORIO comprobar que compila (Gradle build) ANTES de sugerir', severity: 'MANDATORY' });
|
|
729
|
+
patterns.push({ platform: 'android', rule: '✅ OBLIGATORIO seguir flujo BDD → TDD', severity: 'MANDATORY' });
|
|
730
|
+
patterns.push({ platform: 'android', rule: '✅ OBLIGATORIO en producción todo real contra APIs/persistencia', severity: 'MANDATORY' });
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
if (platform === 'backend') {
|
|
734
|
+
// PROHIBICIONES CRÍTICAS Backend
|
|
735
|
+
patterns.push({ platform: 'backend', rule: '❌ NUNCA usar Singleton - usar NestJS DI (@Injectable)', severity: 'CRITICAL' });
|
|
736
|
+
patterns.push({ platform: 'backend', rule: '❌ NUNCA usar console.log/console.error - usar Logger de NestJS', severity: 'CRITICAL' });
|
|
737
|
+
patterns.push({ platform: 'backend', rule: '❌ NUNCA usar any/unknown en TypeScript - usar tipos explícitos o generics', severity: 'CRITICAL' });
|
|
738
|
+
patterns.push({ platform: 'backend', rule: '❌ NUNCA dejar catch vacíos - siempre loggear o propagar (common.error.empty_catch)', severity: 'CRITICAL' });
|
|
739
|
+
patterns.push({ platform: 'backend', rule: '❌ NUNCA mezclar Command y Query en el mismo handler/service - aplicar CQRS', severity: 'CRITICAL' });
|
|
740
|
+
patterns.push({ platform: 'backend', rule: '❌ NUNCA hardcodear secretos - usar variables de entorno (AWS Secrets Manager, Vault)', severity: 'CRITICAL' });
|
|
741
|
+
patterns.push({ platform: 'backend', rule: '❌ NUNCA añadir comentarios en el código', severity: 'CRITICAL' });
|
|
742
|
+
patterns.push({ platform: 'backend', rule: '❌ NUNCA exponer datos sin validar - usar class-validator + DTOs', severity: 'CRITICAL' });
|
|
743
|
+
patterns.push({ platform: 'backend', rule: '❌ NUNCA exponer stack traces en producción', severity: 'CRITICAL' });
|
|
744
|
+
patterns.push({ platform: 'backend', rule: '❌ NUNCA usar mocks en producción - solo datos reales', severity: 'CRITICAL' });
|
|
745
|
+
patterns.push({ platform: 'backend', rule: '❌ NUNCA loggear datos sensibles (passwords, tokens, PII)', severity: 'CRITICAL' });
|
|
746
|
+
patterns.push({ platform: 'backend', rule: '❌ NUNCA usar God classes (servicios >500 líneas)', severity: 'CRITICAL' });
|
|
747
|
+
patterns.push({ platform: 'backend', rule: '❌ NUNCA usar callback hell - usar async/await', severity: 'CRITICAL' });
|
|
748
|
+
patterns.push({ platform: 'backend', rule: '❌ NUNCA poner lógica en controllers - mover a servicios/use cases', severity: 'CRITICAL' });
|
|
749
|
+
|
|
750
|
+
// OBLIGATORIOS Backend
|
|
751
|
+
patterns.push({ platform: 'backend', rule: '✅ OBLIGATORIO usar Repository Pattern (interfaces en domain, impl en infrastructure)', severity: 'MANDATORY' });
|
|
752
|
+
patterns.push({ platform: 'backend', rule: '✅ OBLIGATORIO usar DTOs + class-validator para validación de entrada/salida', severity: 'MANDATORY' });
|
|
753
|
+
patterns.push({ platform: 'backend', rule: '✅ OBLIGATORIO usar Guards para autenticación/autorización (@UseGuards)', severity: 'MANDATORY' });
|
|
754
|
+
patterns.push({ platform: 'backend', rule: '✅ OBLIGATORIO paginación en TODOS los endpoints de listado', severity: 'MANDATORY' });
|
|
755
|
+
patterns.push({ platform: 'backend', rule: '✅ OBLIGATORIO seguir Clean Architecture (Domain → Application → Infrastructure → Presentation)', severity: 'MANDATORY' });
|
|
756
|
+
patterns.push({ platform: 'backend', rule: '✅ OBLIGATORIO aplicar CQRS (Command Query Responsibility Segregation): Commands (write) separados de Queries (read)', severity: 'MANDATORY' });
|
|
757
|
+
patterns.push({ platform: 'backend', rule: '✅ OBLIGATORIO verificar SOLID', severity: 'MANDATORY' });
|
|
758
|
+
patterns.push({ platform: 'backend', rule: '✅ OBLIGATORIO TypeScript strict mode', severity: 'MANDATORY' });
|
|
759
|
+
patterns.push({ platform: 'backend', rule: '✅ OBLIGATORIO usar Use Cases explícitos (CreateOrderUseCase, etc.)', severity: 'MANDATORY' });
|
|
760
|
+
patterns.push({ platform: 'backend', rule: '✅ OBLIGATORIO usar Exception Filters para manejo global de errores', severity: 'MANDATORY' });
|
|
761
|
+
patterns.push({ platform: 'backend', rule: '✅ OBLIGATORIO usar Swagger/OpenAPI para documentación (@nestjs/swagger)', severity: 'MANDATORY' });
|
|
762
|
+
patterns.push({ platform: 'backend', rule: '✅ OBLIGATORIO usar queries parametrizadas (prevenir SQL injection)', severity: 'MANDATORY' });
|
|
763
|
+
patterns.push({ platform: 'backend', rule: '✅ OBLIGATORIO usar índices en columnas frecuentes en WHERE/JOIN', severity: 'MANDATORY' });
|
|
764
|
+
patterns.push({ platform: 'backend', rule: '✅ OBLIGATORIO usar transacciones para operaciones críticas', severity: 'MANDATORY' });
|
|
765
|
+
patterns.push({ platform: 'backend', rule: '✅ OBLIGATORIO usar soft deletes (deleted_at) por defecto', severity: 'MANDATORY' });
|
|
766
|
+
patterns.push({ platform: 'backend', rule: '✅ OBLIGATORIO usar JWT + refresh tokens para autenticación', severity: 'MANDATORY' });
|
|
767
|
+
patterns.push({ platform: 'backend', rule: '✅ OBLIGATORIO usar rate limiting (@nestjs/throttler)', severity: 'MANDATORY' });
|
|
768
|
+
patterns.push({ platform: 'backend', rule: '✅ OBLIGATORIO usar Helmet para security headers', severity: 'MANDATORY' });
|
|
769
|
+
patterns.push({ platform: 'backend', rule: '✅ OBLIGATORIO usar health checks (/health endpoint)', severity: 'MANDATORY' });
|
|
770
|
+
patterns.push({ platform: 'backend', rule: '✅ OBLIGATORIO usar correlation IDs para tracing distribuido', severity: 'MANDATORY' });
|
|
771
|
+
patterns.push({ platform: 'backend', rule: '✅ OBLIGATORIO nombres autodescriptivos en inglés', severity: 'MANDATORY' });
|
|
772
|
+
patterns.push({ platform: 'backend', rule: '✅ OBLIGATORIO comprobar que compila (npm run build) ANTES de sugerir', severity: 'MANDATORY' });
|
|
773
|
+
patterns.push({ platform: 'backend', rule: '✅ OBLIGATORIO seguir flujo BDD → TDD', severity: 'MANDATORY' });
|
|
774
|
+
patterns.push({ platform: 'backend', rule: '✅ OBLIGATORIO coverage >95% en lógica crítica', severity: 'MANDATORY' });
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
if (platform === 'frontend') {
|
|
778
|
+
// PROHIBICIONES CRÍTICAS Frontend
|
|
779
|
+
patterns.push({ platform: 'frontend', rule: '❌ NUNCA usar any/unknown en TypeScript - usar tipos explícitos o generics', severity: 'CRITICAL' });
|
|
780
|
+
patterns.push({ platform: 'frontend', rule: '❌ NUNCA usar class components - usar functional components + hooks', severity: 'CRITICAL' });
|
|
781
|
+
patterns.push({ platform: 'frontend', rule: '❌ NUNCA hardcodear strings - usar i18n (useTranslation)', severity: 'CRITICAL' });
|
|
782
|
+
patterns.push({ platform: 'frontend', rule: '❌ NUNCA dejar catch vacíos - siempre gestionar errores (common.error.empty_catch)', severity: 'CRITICAL' });
|
|
783
|
+
patterns.push({ platform: 'frontend', rule: '❌ NUNCA mezclar operaciones de escritura (commands/mutations) con lecturas (queries) en el mismo hook/service - aplicar CQRS', severity: 'CRITICAL' });
|
|
784
|
+
patterns.push({ platform: 'frontend', rule: '❌ NUNCA añadir comentarios en el código', severity: 'CRITICAL' });
|
|
785
|
+
patterns.push({ platform: 'frontend', rule: '❌ NUNCA usar console.log en producción', severity: 'CRITICAL' });
|
|
786
|
+
patterns.push({ platform: 'frontend', rule: '❌ NUNCA usar Singleton - usar providers/context para DI', severity: 'CRITICAL' });
|
|
787
|
+
patterns.push({ platform: 'frontend', rule: '❌ NUNCA usar índice como key en listas si el orden puede cambiar', severity: 'CRITICAL' });
|
|
788
|
+
patterns.push({ platform: 'frontend', rule: '❌ NUNCA usar prop drilling excesivo - usar Context/Zustand', severity: 'CRITICAL' });
|
|
789
|
+
patterns.push({ platform: 'frontend', rule: '❌ NUNCA renderizar HTML de usuario sin sanitizar (DOMPurify)', severity: 'CRITICAL' });
|
|
790
|
+
patterns.push({ platform: 'frontend', rule: '❌ NUNCA poner tokens en URLs - usar Authorization headers', severity: 'CRITICAL' });
|
|
791
|
+
|
|
792
|
+
// OBLIGATORIOS Frontend
|
|
793
|
+
patterns.push({ platform: 'frontend', rule: '✅ OBLIGATORIO usar TypeScript strict mode', severity: 'MANDATORY' });
|
|
794
|
+
patterns.push({ platform: 'frontend', rule: '✅ OBLIGATORIO usar React functional components + hooks', severity: 'MANDATORY' });
|
|
795
|
+
patterns.push({ platform: 'frontend', rule: '✅ OBLIGATORIO usar TailwindCSS para estilos', severity: 'MANDATORY' });
|
|
796
|
+
patterns.push({ platform: 'frontend', rule: '✅ OBLIGATORIO usar Next.js 15 App Router (app/ directory)', severity: 'MANDATORY' });
|
|
797
|
+
patterns.push({ platform: 'frontend', rule: '✅ OBLIGATORIO usar Server Components por defecto ("use client" solo cuando necesario)', severity: 'MANDATORY' });
|
|
798
|
+
patterns.push({ platform: 'frontend', rule: '✅ OBLIGATORIO usar React Query para server state', severity: 'MANDATORY' });
|
|
799
|
+
patterns.push({ platform: 'frontend', rule: '✅ OBLIGATORIO usar Zustand para estado global', severity: 'MANDATORY' });
|
|
800
|
+
patterns.push({ platform: 'frontend', rule: '✅ OBLIGATORIO usar React Hook Form + Zod para forms', severity: 'MANDATORY' });
|
|
801
|
+
patterns.push({ platform: 'frontend', rule: '✅ OBLIGATORIO API client en capa infrastructure (abstraer axios/fetch)', severity: 'MANDATORY' });
|
|
802
|
+
patterns.push({ platform: 'frontend', rule: '✅ OBLIGATORIO tests con React Testing Library + Playwright', severity: 'MANDATORY' });
|
|
803
|
+
patterns.push({ platform: 'frontend', rule: '✅ OBLIGATORIO seguir Clean Architecture', severity: 'MANDATORY' });
|
|
804
|
+
patterns.push({ platform: 'frontend', rule: '✅ OBLIGATORIO aplicar CQRS (Command Query Responsibility Segregation): separar writes (mutations) de reads (queries)', severity: 'MANDATORY' });
|
|
805
|
+
patterns.push({ platform: 'frontend', rule: '✅ OBLIGATORIO verificar SOLID', severity: 'MANDATORY' });
|
|
806
|
+
patterns.push({ platform: 'frontend', rule: '✅ OBLIGATORIO usar Next/Image para imágenes', severity: 'MANDATORY' });
|
|
807
|
+
patterns.push({ platform: 'frontend', rule: '✅ OBLIGATORIO usar loading.tsx/error.tsx en cada ruta', severity: 'MANDATORY' });
|
|
808
|
+
patterns.push({ platform: 'frontend', rule: '✅ OBLIGATORIO usar semantic HTML + ARIA labels', severity: 'MANDATORY' });
|
|
809
|
+
patterns.push({ platform: 'frontend', rule: '✅ OBLIGATORIO usar keyboard navigation en todos los interactivos', severity: 'MANDATORY' });
|
|
810
|
+
patterns.push({ platform: 'frontend', rule: '✅ OBLIGATORIO WCAG AA mínimo (contraste 4.5:1)', severity: 'MANDATORY' });
|
|
811
|
+
patterns.push({ platform: 'frontend', rule: '✅ OBLIGATORIO nombres autodescriptivos en inglés', severity: 'MANDATORY' });
|
|
812
|
+
patterns.push({ platform: 'frontend', rule: '✅ OBLIGATORIO comprobar que compila y pasa tests ANTES de sugerir', severity: 'MANDATORY' });
|
|
813
|
+
patterns.push({ platform: 'frontend', rule: '✅ OBLIGATORIO seguir flujo BDD → TDD', severity: 'MANDATORY' });
|
|
814
|
+
patterns.push({ platform: 'frontend', rule: '✅ OBLIGATORIO en producción todo real contra APIs', severity: 'MANDATORY' });
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
if (platform === 'gold') {
|
|
818
|
+
// PROHIBICIONES CRÍTICAS Gold (comunes a todas las plataformas)
|
|
819
|
+
patterns.push({ platform: 'gold', rule: '❌ NUNCA usar Singleton - usar Inyección de Dependencias', severity: 'CRITICAL' });
|
|
820
|
+
patterns.push({ platform: 'gold', rule: '❌ NUNCA dejar catch vacíos - siempre loggear o propagar (AST: common.error.empty_catch)', severity: 'CRITICAL' });
|
|
821
|
+
patterns.push({ platform: 'gold', rule: '❌ NUNCA añadir comentarios en el código - nombres autodescriptivos', severity: 'CRITICAL' });
|
|
822
|
+
patterns.push({ platform: 'gold', rule: '❌ NUNCA usar mocks/spies en producción - todo real contra BBDD/servicios', severity: 'CRITICAL' });
|
|
823
|
+
patterns.push({ platform: 'gold', rule: '❌ NUNCA usar --no-verify o GIT_BYPASS_HOOK sin autorización explícita verbal', severity: 'CRITICAL' });
|
|
824
|
+
patterns.push({ platform: 'gold', rule: '❌ NUNCA hardcodear secretos en código - usar variables de entorno', severity: 'CRITICAL' });
|
|
825
|
+
patterns.push({ platform: 'gold', rule: '❌ NUNCA silenciar errores - siempre loggear o propagar', severity: 'CRITICAL' });
|
|
826
|
+
patterns.push({ platform: 'gold', rule: '❌ NUNCA modificar librerías locales (node_modules/@pumuki/...) - reportar bugs', severity: 'CRITICAL' });
|
|
827
|
+
|
|
828
|
+
// OBLIGATORIOS Gold (comunes a todas las plataformas)
|
|
829
|
+
patterns.push({ platform: 'gold', rule: '✅ OBLIGATORIO responder siempre en español', severity: 'MANDATORY' });
|
|
830
|
+
patterns.push({ platform: 'gold', rule: '✅ OBLIGATORIO actuar como Arquitecto de Soluciones y Software Designer', severity: 'MANDATORY' });
|
|
831
|
+
patterns.push({ platform: 'gold', rule: '✅ OBLIGATORIO seguir flujo BDD → TDD (Feature files → Specs → Implementación)', severity: 'MANDATORY' });
|
|
832
|
+
patterns.push({ platform: 'gold', rule: '✅ OBLIGATORIO seguir Clean Architecture y Clean Code (capas, dependencias hacia adentro)', severity: 'MANDATORY' });
|
|
833
|
+
patterns.push({ platform: 'gold', rule: '✅ OBLIGATORIO verificar SOLID (SRP, OCP, LSP, ISP, DIP) en cada cambio', severity: 'MANDATORY' });
|
|
834
|
+
patterns.push({ platform: 'gold', rule: '✅ OBLIGATORIO preferir guard/early returns - evitar pyramid of doom', severity: 'MANDATORY' });
|
|
835
|
+
patterns.push({ platform: 'gold', rule: '✅ OBLIGATORIO nombres autodescriptivos en inglés (todo el código)', severity: 'MANDATORY' });
|
|
836
|
+
patterns.push({ platform: 'gold', rule: '✅ OBLIGATORIO comprobar que compila ANTES de sugerir cualquier cambio', severity: 'MANDATORY' });
|
|
837
|
+
patterns.push({ platform: 'gold', rule: '✅ OBLIGATORIO analizar estructura existente antes de implementar', severity: 'MANDATORY' });
|
|
838
|
+
patterns.push({ platform: 'gold', rule: '✅ OBLIGATORIO usar makeSUT pattern en tests', severity: 'MANDATORY' });
|
|
839
|
+
patterns.push({ platform: 'gold', rule: '✅ OBLIGATORIO usar trackForMemoryLeaks en tests', severity: 'MANDATORY' });
|
|
840
|
+
patterns.push({ platform: 'gold', rule: '✅ OBLIGATORIO preferir spies frente a stubs/mocks en tests', severity: 'MANDATORY' });
|
|
841
|
+
patterns.push({ platform: 'gold', rule: '✅ OBLIGATORIO validar SIEMPRE entradas de usuario', severity: 'MANDATORY' });
|
|
842
|
+
patterns.push({ platform: 'gold', rule: '✅ OBLIGATORIO sanitizar datos (prevenir XSS, SQL Injection)', severity: 'MANDATORY' });
|
|
843
|
+
patterns.push({ platform: 'gold', rule: '✅ OBLIGATORIO principio de menor privilegio (permisos mínimos)', severity: 'MANDATORY' });
|
|
844
|
+
patterns.push({ platform: 'gold', rule: '✅ OBLIGATORIO paginación en todas las listas', severity: 'MANDATORY' });
|
|
845
|
+
patterns.push({ platform: 'gold', rule: '✅ OBLIGATORIO tests como documentación viva (AAA/Given-When-Then)', severity: 'MANDATORY' });
|
|
846
|
+
patterns.push({ platform: 'gold', rule: '✅ OBLIGATORIO cobertura mínima 80%, objetivo 95%+ en lógica crítica', severity: 'MANDATORY' });
|
|
847
|
+
patterns.push({ platform: 'gold', rule: '✅ OBLIGATORIO commits atómicos con Conventional Commits (feat:, fix:, etc.)', severity: 'MANDATORY' });
|
|
848
|
+
patterns.push({ platform: 'gold', rule: '✅ OBLIGATORIO branch naming (feature/, bugfix/, hotfix/, refactor/)', severity: 'MANDATORY' });
|
|
849
|
+
patterns.push({ platform: 'gold', rule: '✅ OBLIGATORIO i18n desde día 1 - no hardcodear strings', severity: 'MANDATORY' });
|
|
850
|
+
patterns.push({ platform: 'gold', rule: '✅ OBLIGATORIO WCAG 2.1 AA mínimo para accesibilidad', severity: 'MANDATORY' });
|
|
851
|
+
patterns.push({ platform: 'gold', rule: '✅ OBLIGATORIO "Measure twice, cut once" - planificar bien antes de implementar', severity: 'MANDATORY' });
|
|
852
|
+
patterns.push({ platform: 'gold', rule: '✅ OBLIGATORIO YAGNI - You Ain\'t Gonna Need It (no sobre-ingeniería)', severity: 'MANDATORY' });
|
|
853
|
+
patterns.push({ platform: 'gold', rule: '✅ OBLIGATORIO KISS - Keep It Simple, Stupid (solución más simple que funcione)', severity: 'MANDATORY' });
|
|
854
|
+
patterns.push({ platform: 'gold', rule: '✅ OBLIGATORIO Fail Fast - validar precondiciones al inicio', severity: 'MANDATORY' });
|
|
855
|
+
patterns.push({ platform: 'gold', rule: '✅ OBLIGATORIO inmutabilidad por defecto (const, readonly, let > var)', severity: 'MANDATORY' });
|
|
856
|
+
patterns.push({ platform: 'gold', rule: '✅ OBLIGATORIO composición > herencia', severity: 'MANDATORY' });
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
return patterns;
|
|
860
|
+
}
|
|
861
|
+
|
|
579
862
|
/**
|
|
580
863
|
* AI Gate Check - MANDATORY at start of every AI response
|
|
581
864
|
* Returns BLOCKED or ALLOWED status with auto-fixes applied
|
|
865
|
+
* NOW INCLUDES: mandatory_rules that AI MUST read and follow
|
|
582
866
|
*/
|
|
583
867
|
async function aiGateCheck() {
|
|
584
868
|
const startedAt = Date.now();
|
|
@@ -683,19 +967,71 @@ async function aiGateCheck() {
|
|
|
683
967
|
}
|
|
684
968
|
}
|
|
685
969
|
|
|
970
|
+
let mandatoryRules = null;
|
|
971
|
+
let detectedPlatforms = [];
|
|
972
|
+
try {
|
|
973
|
+
const orchestrator = getCompositionRoot().getOrchestrator();
|
|
974
|
+
const contextDecision = await orchestrator.analyzeContext();
|
|
975
|
+
if (contextDecision && contextDecision.platforms) {
|
|
976
|
+
detectedPlatforms = contextDecision.platforms.map(p => p.platform || p);
|
|
977
|
+
}
|
|
978
|
+
const fallbackPlatforms = ['backend', 'frontend', 'ios', 'android'];
|
|
979
|
+
const platformsForRules = (detectedPlatforms.length > 0 ? detectedPlatforms : fallbackPlatforms)
|
|
980
|
+
.filter(Boolean);
|
|
981
|
+
const normalizedPlatforms = Array.from(new Set(platformsForRules));
|
|
982
|
+
const rulesData = await loadPlatformRules(normalizedPlatforms);
|
|
983
|
+
const rulesSample = rulesData.criticalRules.slice(0, 5).map(r => r.rule || r);
|
|
984
|
+
const rulesCount = rulesData.criticalRules.length;
|
|
985
|
+
mandatoryRules = {
|
|
986
|
+
platforms: normalizedPlatforms,
|
|
987
|
+
criticalRules: rulesData.criticalRules,
|
|
988
|
+
rulesLoaded: Object.keys(rulesData.rules),
|
|
989
|
+
totalRulesCount: rulesCount,
|
|
990
|
+
rulesSample: rulesSample,
|
|
991
|
+
proofOfRead: `✅ VERIFIED: ${rulesCount} critical rules loaded from ${Object.keys(rulesData.rules).join(', ')}`
|
|
992
|
+
};
|
|
993
|
+
} catch (error) {
|
|
994
|
+
if (process.env.DEBUG) {
|
|
995
|
+
process.stderr.write(`[MCP] Failed to load mandatory rules: ${error.message}\n`);
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
const fallbackPlatforms = ['backend', 'frontend', 'ios', 'android'];
|
|
999
|
+
const normalizedPlatforms = Array.from(new Set((detectedPlatforms.length > 0 ? detectedPlatforms : fallbackPlatforms).filter(Boolean)));
|
|
1000
|
+
mandatoryRules = {
|
|
1001
|
+
platforms: normalizedPlatforms,
|
|
1002
|
+
criticalRules: [],
|
|
1003
|
+
rulesLoaded: [],
|
|
1004
|
+
status: 'FAILED_TO_LOAD',
|
|
1005
|
+
error: `Failed to load rules content: ${error && error.message ? error.message : String(error)}`
|
|
1006
|
+
};
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
const rulesLoadedSuccessfully = mandatoryRules &&
|
|
1010
|
+
mandatoryRules.criticalRules &&
|
|
1011
|
+
mandatoryRules.criticalRules.length > 0;
|
|
1012
|
+
|
|
1013
|
+
if (!rulesLoadedSuccessfully) {
|
|
1014
|
+
violations.push('❌ RULES_NOT_LOADED: Critical platform rules could not be loaded. AI cannot proceed without reading mandatory rules.');
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
const finalBlocked = isBlocked || !rulesLoadedSuccessfully;
|
|
1018
|
+
|
|
686
1019
|
return {
|
|
687
|
-
status:
|
|
1020
|
+
status: finalBlocked ? 'BLOCKED' : 'ALLOWED',
|
|
688
1021
|
timestamp: new Date().toISOString(),
|
|
689
1022
|
branch: currentBranch,
|
|
690
1023
|
violations,
|
|
691
1024
|
warnings,
|
|
692
1025
|
autoFixes,
|
|
693
|
-
|
|
1026
|
+
mandatory_rules: rulesLoadedSuccessfully
|
|
1027
|
+
? { ...mandatoryRules, status: 'LOADED_OK' }
|
|
1028
|
+
: mandatoryRules,
|
|
1029
|
+
summary: finalBlocked
|
|
694
1030
|
? `🚫 BLOCKED: ${violations.length} violation(s). Fix before proceeding.`
|
|
695
|
-
: `🚦 ALLOWED: Gate passed
|
|
696
|
-
instructions:
|
|
1031
|
+
: `🚦 ALLOWED: Gate passed. ${mandatoryRules.totalRulesCount} critical rules loaded and verified.`,
|
|
1032
|
+
instructions: finalBlocked
|
|
697
1033
|
? 'DO NOT proceed with user task. Announce violations and fix them first.'
|
|
698
|
-
: '
|
|
1034
|
+
: `✅ ${mandatoryRules.totalRulesCount} RULES LOADED. Sample: ${mandatoryRules.rulesSample.slice(0, 2).join(' | ')}... Review ALL rules in mandatory_rules.criticalRules before ANY code generation.`
|
|
699
1035
|
};
|
|
700
1036
|
};
|
|
701
1037
|
|
|
@@ -712,11 +1048,59 @@ async function aiGateCheck() {
|
|
|
712
1048
|
violations: ['❌ GATE_TIMEOUT: AI gate check timed out. Retry or run ai-start manually.'],
|
|
713
1049
|
warnings: [],
|
|
714
1050
|
autoFixes: [],
|
|
1051
|
+
mandatory_rules: {
|
|
1052
|
+
platforms: ['backend', 'frontend', 'ios', 'android'],
|
|
1053
|
+
criticalRules: [],
|
|
1054
|
+
rulesLoaded: [],
|
|
1055
|
+
warning: '⚠️ AI MUST read and follow these rules before ANY code generation or modification',
|
|
1056
|
+
error: 'Rules could not be loaded due to timeout'
|
|
1057
|
+
},
|
|
715
1058
|
summary: '🚫 BLOCKED: Gate check timed out.',
|
|
716
1059
|
instructions: 'DO NOT proceed with user task. Retry the gate check.'
|
|
717
1060
|
};
|
|
718
1061
|
}
|
|
719
1062
|
|
|
1063
|
+
/**
|
|
1064
|
+
* Read platform rules handler - returns critical rules for a specific platform
|
|
1065
|
+
*/
|
|
1066
|
+
async function readPlatformRulesHandler(params) {
|
|
1067
|
+
const platform = params.platform;
|
|
1068
|
+
if (!platform) {
|
|
1069
|
+
return {
|
|
1070
|
+
success: false,
|
|
1071
|
+
error: 'Platform is required. Use: ios, android, backend, or frontend'
|
|
1072
|
+
};
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
try {
|
|
1076
|
+
const rulesData = await loadPlatformRules([platform]);
|
|
1077
|
+
const DynamicRulesLoader = require('../../application/services/DynamicRulesLoader');
|
|
1078
|
+
const loader = new DynamicRulesLoader();
|
|
1079
|
+
const fullContent = await loader.loadRule(`rules${platform}.mdc`);
|
|
1080
|
+
|
|
1081
|
+
return {
|
|
1082
|
+
success: true,
|
|
1083
|
+
platform,
|
|
1084
|
+
rulesLoaded: true,
|
|
1085
|
+
criticalRules: rulesData.criticalRules,
|
|
1086
|
+
fullRulesContent: fullContent,
|
|
1087
|
+
warning: `⚠️ YOU MUST FOLLOW ALL THESE RULES. Violations will block commits.`,
|
|
1088
|
+
instructions: [
|
|
1089
|
+
`❌ NEVER violate any rule marked with ❌ or NUNCA/PROHIBIDO`,
|
|
1090
|
+
`✅ ALWAYS follow rules marked with ✅ or OBLIGATORIO/SIEMPRE`,
|
|
1091
|
+
`🚨 If you violate these rules, the commit will be BLOCKED`,
|
|
1092
|
+
`📝 Read the fullRulesContent carefully before generating ANY code`
|
|
1093
|
+
]
|
|
1094
|
+
};
|
|
1095
|
+
} catch (error) {
|
|
1096
|
+
return {
|
|
1097
|
+
success: false,
|
|
1098
|
+
platform,
|
|
1099
|
+
error: `Failed to load rules: ${error.message}`
|
|
1100
|
+
};
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
1103
|
+
|
|
720
1104
|
/**
|
|
721
1105
|
* Validate and fix common issues
|
|
722
1106
|
*/
|
|
@@ -1010,6 +1394,21 @@ async function handleMcpMessage(message) {
|
|
|
1010
1394
|
name: 'ai_gate_check',
|
|
1011
1395
|
description: '🚦 MANDATORY gate check',
|
|
1012
1396
|
inputSchema: { type: 'object', properties: {} }
|
|
1397
|
+
},
|
|
1398
|
+
{
|
|
1399
|
+
name: 'read_platform_rules',
|
|
1400
|
+
description: '📚 MANDATORY: Read platform-specific rules BEFORE any code generation. Returns critical rules that AI MUST follow.',
|
|
1401
|
+
inputSchema: {
|
|
1402
|
+
type: 'object',
|
|
1403
|
+
properties: {
|
|
1404
|
+
platform: {
|
|
1405
|
+
type: 'string',
|
|
1406
|
+
enum: ['ios', 'android', 'backend', 'frontend'],
|
|
1407
|
+
description: 'Platform to load rules for'
|
|
1408
|
+
}
|
|
1409
|
+
},
|
|
1410
|
+
required: ['platform']
|
|
1411
|
+
}
|
|
1013
1412
|
}
|
|
1014
1413
|
]
|
|
1015
1414
|
}
|
|
@@ -1043,6 +1442,9 @@ async function handleMcpMessage(message) {
|
|
|
1043
1442
|
case 'ai_gate_check':
|
|
1044
1443
|
result = await aiGateCheck();
|
|
1045
1444
|
break;
|
|
1445
|
+
case 'read_platform_rules':
|
|
1446
|
+
result = await readPlatformRulesHandler(toolParams);
|
|
1447
|
+
break;
|
|
1046
1448
|
default:
|
|
1047
1449
|
return {
|
|
1048
1450
|
jsonrpc: '2.0',
|