pumuki 6.3.172 → 6.3.174
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/AGENTS.md +1 -16
- package/CHANGELOG.md +0 -101
- package/README.md +10 -14
- package/VERSION +1 -1
- package/core/facts/detectors/text/android.test.ts +0 -2827
- package/core/facts/detectors/text/android.ts +182 -5121
- package/core/facts/detectors/text/ios.test.ts +12 -290
- package/core/facts/detectors/text/ios.ts +28 -301
- package/core/facts/detectors/typescript/index.test.ts +139 -3733
- package/core/facts/detectors/typescript/index.ts +264 -4959
- package/core/facts/extractHeuristicFacts.ts +11 -328
- package/core/gate/evaluateRules.test.ts +0 -7
- package/core/gate/evaluateRules.ts +2 -1
- package/core/rules/presets/heuristics/android.test.ts +1 -399
- package/core/rules/presets/heuristics/android.ts +1 -1481
- package/core/rules/presets/heuristics/ios.test.ts +1 -11
- package/core/rules/presets/heuristics/ios.ts +0 -36
- package/core/rules/presets/heuristics/typescript.test.ts +2 -158
- package/core/rules/presets/heuristics/typescript.ts +0 -508
- package/core/rules/presets/iosEnterpriseRuleSet.test.ts +0 -5
- package/core/rules/presets/iosEnterpriseRuleSet.ts +5 -5
- package/docs/README.md +3 -3
- package/docs/operations/RELEASE_NOTES.md +1 -94
- package/docs/operations/framework-menu-consumer-walkthrough.md +15 -18
- package/docs/product/API_REFERENCE.md +1 -1
- package/docs/product/CONFIGURATION.md +0 -7
- package/docs/product/USAGE.md +1 -1
- package/docs/validation/README.md +1 -3
- package/docs/validation/ios-avdlee-parity-matrix.md +1 -1
- package/integrations/config/skillsCompilerTemplates.test.ts +0 -145
- package/integrations/config/skillsCompilerTemplates.ts +2 -1013
- package/integrations/config/skillsDetectorRegistry.ts +8 -523
- package/integrations/config/skillsMarkdownRules.ts +8 -1088
- package/integrations/config/skillsRuleSet.ts +3 -44
- package/integrations/evidence/buildEvidence.ts +5 -34
- package/integrations/evidence/platformSummary.test.ts +9 -73
- package/integrations/evidence/platformSummary.ts +7 -165
- package/integrations/evidence/repoState.ts +0 -3
- package/integrations/evidence/rulesCoverage.ts +0 -83
- package/integrations/evidence/schema.ts +0 -29
- package/integrations/evidence/writeEvidence.test.ts +0 -4
- package/integrations/evidence/writeEvidence.ts +2 -41
- package/integrations/gate/evaluateAiGate.ts +8 -312
- package/integrations/gate/remediationCatalog.ts +2 -20
- package/integrations/gate/stagePolicies.ts +18 -24
- package/integrations/git/astIntelligenceDualValidation.ts +2 -2
- package/integrations/git/gitAtomicity.ts +39 -284
- package/integrations/git/resolveGitRefs.ts +6 -35
- package/integrations/git/runPlatformGate.ts +143 -512
- package/integrations/git/runPlatformGateOutput.ts +8 -13
- package/integrations/git/stageRunners.ts +41 -25
- package/integrations/lifecycle/adapter.ts +0 -24
- package/integrations/lifecycle/audit.ts +16 -14
- package/integrations/lifecycle/cli.ts +20 -37
- package/integrations/lifecycle/cliSdd.ts +3 -4
- package/integrations/lifecycle/doctor.ts +1 -1
- package/integrations/lifecycle/packageInfo.ts +1 -118
- package/integrations/lifecycle/policyReconcile.ts +4 -27
- package/integrations/lifecycle/preWriteAutomation.ts +5 -5
- package/integrations/lifecycle/state.ts +1 -8
- package/integrations/lifecycle/watch.ts +8 -28
- package/integrations/mcp/aiGateCheck.ts +10 -194
- package/integrations/mcp/autoExecuteAiStart.ts +4 -7
- package/integrations/mcp/enterpriseServer.ts +3 -19
- package/integrations/mcp/preFlightCheck.ts +10 -89
- package/integrations/policy/gitAtomicityEnforcement.ts +2 -2
- package/integrations/policy/heuristicsEnforcement.ts +2 -2
- package/integrations/policy/policyProfiles.ts +18 -24
- package/integrations/policy/preWriteEnforcement.ts +1 -1
- package/integrations/policy/sddCompletenessEnforcement.ts +2 -2
- package/integrations/policy/skillsEnforcement.ts +47 -1
- package/integrations/policy/tddBddEnforcement.ts +2 -2
- package/integrations/sdd/evidenceScaffold.ts +8 -124
- package/integrations/tdd/contract.ts +0 -1
- package/integrations/tdd/enforcement.ts +0 -103
- package/integrations/tdd/types.ts +0 -6
- package/package.json +1 -1
- package/scripts/check-tracking-single-active.sh +1 -1
- package/scripts/framework-menu-advanced-view-lib.ts +0 -49
- package/scripts/framework-menu-consumer-actions-lib.ts +32 -32
- package/scripts/framework-menu-consumer-preflight-render.ts +0 -10
- package/scripts/framework-menu-consumer-preflight-run.ts +5 -31
- package/scripts/framework-menu-consumer-preflight-types.ts +0 -12
- package/scripts/framework-menu-consumer-runtime-actions.ts +5 -11
- package/scripts/framework-menu-consumer-runtime-audit.ts +28 -0
- package/scripts/framework-menu-consumer-runtime-evidence-classic.ts +42 -118
- package/scripts/framework-menu-consumer-runtime-lib.ts +0 -38
- package/scripts/framework-menu-consumer-runtime-menu.ts +15 -55
- package/scripts/framework-menu-consumer-runtime-types.ts +0 -4
- package/scripts/framework-menu-evidence-summary-read.ts +1 -17
- package/scripts/framework-menu-evidence-summary-types.ts +0 -3
- package/scripts/framework-menu-layout-data.ts +23 -3
- package/scripts/framework-menu-system-notifications-cause.ts +1 -24
- package/scripts/framework-menu-system-notifications-env.ts +0 -8
- package/scripts/framework-menu-system-notifications-gate.ts +2 -9
- package/scripts/framework-menu-system-notifications-macos-applescript-dialog.ts +1 -1
- package/scripts/framework-menu-system-notifications-macos-dialog-payload.ts +2 -14
- package/scripts/framework-menu-system-notifications-macos-swift-source.ts +1 -1
- package/scripts/framework-menu-system-notifications-payloads-blocked.ts +4 -128
- package/scripts/framework-menu-system-notifications-payloads.ts +1 -8
- package/scripts/framework-menu-system-notifications-remediation.ts +1 -15
- package/scripts/framework-menu-system-notifications-text.ts +1 -7
- package/scripts/framework-menu.ts +2 -37
- package/scripts/package-install-smoke-consumer-git-repo-lib.ts +1 -10
- package/scripts/package-install-smoke-consumer-npm-lib.ts +9 -46
- package/skills.lock.json +1244 -807
- package/integrations/evidence/trackingContract.ts +0 -17
- package/integrations/gate/blockingCause.ts +0 -40
- package/integrations/gate/governanceActionCatalog.ts +0 -296
- package/integrations/gate/runPlatformGateConfig.ts +0 -55
- package/integrations/gate/runPlatformGateDefaults.ts +0 -19
- package/integrations/lifecycle/bootstrapManifest.ts +0 -248
- package/integrations/lifecycle/cliGovernanceConsole.ts +0 -69
- package/integrations/lifecycle/governanceNextAction.ts +0 -181
- package/integrations/lifecycle/governanceObservationSnapshot.ts +0 -376
- package/integrations/lifecycle/trackingState.ts +0 -403
- package/integrations/mcp/alignedPlatformGate.ts +0 -248
- package/integrations/mcp/readMcpPrePushStdin.ts +0 -7
- package/scripts/build-ruralgo-s1-evidence-pack.ts +0 -85
- package/scripts/ruralgo-s1-evidence-pack-lib.ts +0 -200
|
@@ -60,13 +60,6 @@ const isTypeScriptHeuristicTargetPath = (
|
|
|
60
60
|
);
|
|
61
61
|
};
|
|
62
62
|
|
|
63
|
-
const isTypeScriptFrontendPath = (path: string): boolean => {
|
|
64
|
-
if (!isTypeScriptHeuristicTargetPath(path)) {
|
|
65
|
-
return false;
|
|
66
|
-
}
|
|
67
|
-
return path.startsWith('apps/frontend/') || path.startsWith('apps/web/');
|
|
68
|
-
};
|
|
69
|
-
|
|
70
63
|
const isTypeScriptDomainOrApplicationPath = (path: string): boolean => {
|
|
71
64
|
if (!isTypeScriptHeuristicTargetPath(path)) {
|
|
72
65
|
return false;
|
|
@@ -98,63 +91,6 @@ const isAndroidKotlinPath = (path: string): boolean => {
|
|
|
98
91
|
return (path.endsWith('.kt') || path.endsWith('.kts')) && path.startsWith('apps/android/');
|
|
99
92
|
};
|
|
100
93
|
|
|
101
|
-
const isAndroidJavaPath = (path: string): boolean => {
|
|
102
|
-
return path.endsWith('.java') && path.startsWith('apps/android/');
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
const isAndroidSourcePath = (path: string): boolean => {
|
|
106
|
-
return isAndroidKotlinPath(path) || isAndroidJavaPath(path);
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
const isAndroidGradlePath = (path: string): boolean => {
|
|
110
|
-
const normalized = path.replace(/\\/g, '/').toLowerCase();
|
|
111
|
-
if (!normalized.startsWith('apps/android/')) {
|
|
112
|
-
return false;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
return (
|
|
116
|
-
normalized.endsWith('/build.gradle') ||
|
|
117
|
-
normalized.endsWith('/build.gradle.kts') ||
|
|
118
|
-
normalized.endsWith('.gradle') ||
|
|
119
|
-
normalized.endsWith('.gradle.kts')
|
|
120
|
-
);
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
const isAndroidVersionCatalogPath = (path: string): boolean => {
|
|
124
|
-
const normalized = path.replace(/\\/g, '/').toLowerCase();
|
|
125
|
-
return normalized.startsWith('apps/android/') && normalized.endsWith('libs.versions.toml');
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
const isAndroidLocalizedStringsXmlPath = (path: string): boolean => {
|
|
129
|
-
const normalized = path.replace(/\\/g, '/').toLowerCase();
|
|
130
|
-
return (
|
|
131
|
-
normalized.startsWith('apps/android/') &&
|
|
132
|
-
/\/res\/values-[^/]+\/strings\.xml$/.test(normalized)
|
|
133
|
-
);
|
|
134
|
-
};
|
|
135
|
-
|
|
136
|
-
const isAndroidLocalizedPluralsXmlPath = (path: string): boolean => {
|
|
137
|
-
const normalized = path.replace(/\\/g, '/').toLowerCase();
|
|
138
|
-
return (
|
|
139
|
-
normalized.startsWith('apps/android/') &&
|
|
140
|
-
/\/res\/values-[^/]+\/plurals\.xml$/.test(normalized)
|
|
141
|
-
);
|
|
142
|
-
};
|
|
143
|
-
|
|
144
|
-
const isAndroidInstrumentedTestPath = (path: string): boolean => {
|
|
145
|
-
const normalized = path.replace(/\\/g, '/').toLowerCase();
|
|
146
|
-
return normalized.startsWith('apps/android/') && normalized.includes('/androidtest/');
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
const isAndroidJvmTestPath = (path: string): boolean => {
|
|
150
|
-
const normalized = path.replace(/\\/g, '/').toLowerCase();
|
|
151
|
-
return (
|
|
152
|
-
normalized.startsWith('apps/android/') &&
|
|
153
|
-
normalized.includes('/test/') &&
|
|
154
|
-
!normalized.includes('/androidtest/')
|
|
155
|
-
);
|
|
156
|
-
};
|
|
157
|
-
|
|
158
94
|
const isAndroidPresentationPath = (path: string): boolean => {
|
|
159
95
|
return isAndroidKotlinPath(path) && path.includes('/presentation/');
|
|
160
96
|
};
|
|
@@ -210,16 +146,6 @@ const isKotlinTestPath = (path: string): boolean => {
|
|
|
210
146
|
);
|
|
211
147
|
};
|
|
212
148
|
|
|
213
|
-
const isJavaTestPath = (path: string): boolean => {
|
|
214
|
-
const normalized = path.toLowerCase();
|
|
215
|
-
return (
|
|
216
|
-
normalized.includes('/test/') ||
|
|
217
|
-
normalized.includes('/androidtest/') ||
|
|
218
|
-
normalized.endsWith('test.java') ||
|
|
219
|
-
normalized.endsWith('tests.java')
|
|
220
|
-
);
|
|
221
|
-
};
|
|
222
|
-
|
|
223
149
|
const isExcludedProjectScanPath = (path: string): boolean => {
|
|
224
150
|
const normalized = path.replace(/\\/g, '/').toLowerCase();
|
|
225
151
|
return (
|
|
@@ -475,10 +401,6 @@ const astDetectorRegistry: ReadonlyArray<ASTDetectorRegistryEntry> = [
|
|
|
475
401
|
{ detect: TS.hasSetTimeoutStringCallback, ruleId: 'heuristics.ts.set-timeout-string.ast', code: 'HEURISTICS_SET_TIMEOUT_STRING_AST', message: 'AST heuristic detected setTimeout with a string callback.' },
|
|
476
402
|
{ detect: TS.hasSetIntervalStringCallback, ruleId: 'heuristics.ts.set-interval-string.ast', code: 'HEURISTICS_SET_INTERVAL_STRING_AST', message: 'AST heuristic detected setInterval with a string callback.' },
|
|
477
403
|
{ detect: TS.hasAsyncPromiseExecutor, ruleId: 'heuristics.ts.new-promise-async.ast', code: 'HEURISTICS_NEW_PROMISE_ASYNC_AST', message: 'AST heuristic detected async Promise executor usage.' },
|
|
478
|
-
{ detect: TS.hasCallbackHellPattern, ruleId: 'heuristics.ts.callback-hell.ast', code: 'HEURISTICS_CALLBACK_HELL_AST', message: 'AST heuristic detected callback hell / nested promise callback usage.' },
|
|
479
|
-
{ detect: TS.hasMagicNumberPattern, ruleId: 'heuristics.ts.magic-numbers.ast', code: 'HEURISTICS_MAGIC_NUMBERS_AST', message: 'AST heuristic detected magic number usage.' },
|
|
480
|
-
{ detect: TS.hasHardcodedValuePattern, ruleId: 'heuristics.ts.hardcoded-values.ast', code: 'HEURISTICS_HARDCODED_VALUES_AST', message: 'AST heuristic detected hardcoded config value usage.' },
|
|
481
|
-
{ detect: TS.hasEnvDefaultFallbackPattern, ruleId: 'heuristics.ts.env-default-fallback.ast', code: 'HEURISTICS_ENV_DEFAULT_FALLBACK_AST', message: 'AST heuristic detected environment default fallback usage.' },
|
|
482
404
|
{ detect: TS.hasWithStatement, ruleId: 'heuristics.ts.with-statement.ast', code: 'HEURISTICS_WITH_STATEMENT_AST', message: 'AST heuristic detected with-statement usage.' },
|
|
483
405
|
{ detect: TS.hasDeleteOperator, ruleId: 'heuristics.ts.delete-operator.ast', code: 'HEURISTICS_DELETE_OPERATOR_AST', message: 'AST heuristic detected delete-operator usage.' },
|
|
484
406
|
{ detect: TS.hasDebuggerStatement, ruleId: 'heuristics.ts.debugger.ast', code: 'HEURISTICS_DEBUGGER_AST', message: 'AST heuristic detected debugger statement usage.' },
|
|
@@ -488,34 +410,7 @@ const astDetectorRegistry: ReadonlyArray<ASTDetectorRegistryEntry> = [
|
|
|
488
410
|
{ detect: TS.hasOverrideMethodThrowingNotImplemented, ruleId: 'heuristics.ts.solid.lsp.override-not-implemented.ast', code: 'HEURISTICS_SOLID_LSP_OVERRIDE_NOT_IMPLEMENTED_AST', message: 'AST heuristic detected LSP risk: override throws not-implemented/unsupported.' },
|
|
489
411
|
{ detect: TS.hasFrameworkDependencyImport, ruleId: 'heuristics.ts.solid.dip.framework-import.ast', code: 'HEURISTICS_SOLID_DIP_FRAMEWORK_IMPORT_AST', message: 'AST heuristic detected DIP risk: framework dependency imported in domain/application code.', pathCheck: isTypeScriptDomainOrApplicationPath },
|
|
490
412
|
{ detect: TS.hasConcreteDependencyInstantiation, ruleId: 'heuristics.ts.solid.dip.concrete-instantiation.ast', code: 'HEURISTICS_SOLID_DIP_CONCRETE_INSTANTIATION_AST', message: 'AST heuristic detected DIP risk: direct instantiation of concrete framework dependency.', pathCheck: isTypeScriptDomainOrApplicationPath },
|
|
491
|
-
{ detect: (ast) => TS.findCleanArchitectureMatch(ast) !== undefined, ruleId: 'heuristics.ts.clean-architecture.ast', code: 'HEURISTICS_CLEAN_ARCHITECTURE_AST', message: 'AST heuristic detected clean architecture dependency direction risk in domain/application code.', pathCheck: isTypeScriptDomainOrApplicationPath },
|
|
492
|
-
{ detect: TS.hasProductionMockCall, ruleId: 'heuristics.ts.production-mock.ast', code: 'HEURISTICS_PRODUCTION_MOCK_AST', message: 'AST heuristic detected production mock usage in backend runtime code.', pathCheck: (path) => path.startsWith('apps/backend/') },
|
|
493
|
-
{ detect: TS.hasExceptionFilterClass, ruleId: 'heuristics.ts.exception-filter.ast', code: 'HEURISTICS_EXCEPTION_FILTER_AST', message: 'AST heuristic detected global exception filter usage in backend runtime code.', pathCheck: (path) => path.startsWith('apps/backend/') },
|
|
494
|
-
{ detect: TS.hasGuardUseGuardsJwtAuthGuard, ruleId: 'heuristics.ts.guards-useguards-jwtauthguard.ast', code: 'HEURISTICS_GUARDS_USEGUARDS_JWTAUTHGUARD_AST', message: 'AST heuristic detected @UseGuards(JwtAuthGuard) usage in backend runtime code.', pathCheck: (path) => path.startsWith('apps/backend/') },
|
|
495
|
-
{ detect: TS.hasUseInterceptorsLoggingTransform, ruleId: 'heuristics.ts.interceptors-useinterceptors-logging-transform.ast', code: 'HEURISTICS_INTERCEPTORS_USEINTERCEPTORS_LOGGING_TRANSFORM_AST', message: 'AST heuristic detected @UseInterceptors logging/transform usage in backend runtime code.', pathCheck: (path) => path.startsWith('apps/backend/') },
|
|
496
|
-
{ detect: TS.hasSensitiveLogCall, ruleId: 'heuristics.ts.no-sensitive-log.ast', code: 'HEURISTICS_NO_SENSITIVE_LOG_AST', message: 'AST heuristic detected sensitive data emitted to backend logs.', pathCheck: (path) => path.startsWith('apps/backend/') },
|
|
497
|
-
{ detect: TS.hasCorrelationIdsPattern, ruleId: 'heuristics.ts.correlation-ids.ast', code: 'HEURISTICS_CORRELATION_IDS_AST', message: 'AST heuristic detected correlation IDs propagation in backend runtime code.', pathCheck: (path) => path.startsWith('apps/backend/') },
|
|
498
|
-
{ detect: TS.hasCorsConfiguredPattern, ruleId: 'heuristics.ts.cors-configured.ast', code: 'HEURISTICS_CORS_CONFIGURED_AST', message: 'AST heuristic detected backend CORS configuration with allowed origins.', pathCheck: (path) => path.startsWith('apps/backend/') },
|
|
499
|
-
{ detect: TS.hasValidationPipeGlobalPattern, ruleId: 'heuristics.ts.validationpipe-global.ast', code: 'HEURISTICS_VALIDATIONPIPE_GLOBAL_AST', message: 'AST heuristic detected global ValidationPipe configuration with whitelist enabled.', pathCheck: (path) => path.startsWith('apps/backend/') },
|
|
500
|
-
{ detect: TS.hasApiVersioningPattern, ruleId: 'heuristics.ts.versionado-api-v1-api-v2.ast', code: 'HEURISTICS_VERSIONADO_API_V1_API_V2_AST', message: 'AST heuristic detected backend API versioning through versioned NestJS controllers.', pathCheck: (path) => path.startsWith('apps/backend/') },
|
|
501
|
-
{ detect: TS.hasValidationConfigPattern, ruleId: 'heuristics.ts.validation-config.ast', code: 'HEURISTICS_VALIDATION_CONFIG_AST', message: 'AST heuristic detected backend config validation in ConfigModule.', pathCheck: (path) => path.startsWith('apps/backend/') },
|
|
502
|
-
{ detect: TS.hasClassValidatorDecoratorsPattern, ruleId: 'heuristics.ts.class-validator-decorators.ast', code: 'HEURISTICS_CLASS_VALIDATOR_DECORATORS_AST', message: 'AST heuristic detected class-validator decorator usage in backend DTOs.', pathCheck: (path) => path.startsWith('apps/backend/') },
|
|
503
|
-
{ detect: TS.hasClassTransformerDecoratorsPattern, ruleId: 'heuristics.ts.class-transformer-decorators.ast', code: 'HEURISTICS_CLASS_TRANSFORMER_DECORATORS_AST', message: 'AST heuristic detected class-transformer decorator usage in backend DTOs.', pathCheck: (path) => path.startsWith('apps/backend/') },
|
|
504
|
-
{ detect: TS.hasInputValidationPattern, ruleId: 'heuristics.ts.input-validation-siempre-validar-con-dtos.ast', code: 'HEURISTICS_INPUT_VALIDATION_SIEMPRE_VALIDAR_CON_DTOS_AST', message: 'AST heuristic detected backend controller input DTO validation through typed NestJS route parameters.', pathCheck: (path) => path.startsWith('apps/backend/') },
|
|
505
|
-
{ detect: TS.hasNestedValidationPattern, ruleId: 'heuristics.ts.nested-validation-validatenested-type.ast', code: 'HEURISTICS_NESTED_VALIDATION_VALIDATENESTED_TYPE_AST', message: 'AST heuristic detected backend nested DTO validation through @ValidateNested() and @Type().', pathCheck: (path) => path.startsWith('apps/backend/') },
|
|
506
|
-
{ detect: TS.hasDtoBoundaryPattern, ruleId: 'heuristics.ts.dtos-en-boundaries-validacio-n-en-entrada-salida.ast', code: 'HEURISTICS_DTOS_EN_BOUNDARIES_VALIDACIO_N_EN_ENTRADA_SALIDA_AST', message: 'AST heuristic detected backend DTO boundary classes with explicit contract boundaries.', pathCheck: (path) => path.startsWith('apps/backend/') },
|
|
507
|
-
{ detect: TS.hasSeparatedDtoPattern, ruleId: 'heuristics.ts.dtos-separados-createorderdto-updateorderdto-orderresponsedto.ast', code: 'HEURISTICS_DTOS_SEPARADOS_CREATEORDERDTO_UPDATEORDERDTO_ORDERRESPONSEDTO_AST', message: 'AST heuristic detected backend DTO classes split into create, update and response contracts.', pathCheck: (path) => path.startsWith('apps/backend/') },
|
|
508
|
-
{ detect: TS.hasBackendReturnDtosExposureUsage, locateLines: TS.findBackendReturnDtosExposureLines, ruleId: 'heuristics.ts.return-dtos-no-exponer-entidades-directamente.ast', code: 'HEURISTICS_TS_RETURN_DTOS_NO_EXPONER_ENTIDADES_DIRECTAMENTE_AST', message: 'AST heuristic detected backend code returning entities directly instead of DTOs.', pathCheck: (path) => path.startsWith('apps/backend/'), excludePaths: [isTestPath] },
|
|
509
|
-
{ detect: TS.hasBackendCriticalTransactionsUsage, locateLines: TS.findBackendCriticalTransactionsLines, ruleId: 'heuristics.ts.transacciones-para-operaciones-cri-ticas.ast', code: 'HEURISTICS_TS_TRANSACCIONES_PARA_OPERACIONES_CRI_TICAS_AST', message: 'AST heuristic detected backend transaction usage for critical operations.', pathCheck: (path) => path.startsWith('apps/backend/'), excludePaths: [isTestPath] },
|
|
510
|
-
{ detect: TS.hasBackendMultiTableTransactionsUsage, locateLines: TS.findBackendMultiTableTransactionsLines, ruleId: 'heuristics.ts.transacciones-para-operaciones-multi-tabla.ast', code: 'HEURISTICS_TS_TRANSACCIONES_PARA_OPERACIONES_MULTI_TABLA_AST', message: 'AST heuristic detected backend transaction usage for multi-table operations.', pathCheck: (path) => path.startsWith('apps/backend/'), excludePaths: [isTestPath] },
|
|
511
|
-
{ detect: TS.hasPrometheusMetricsPattern, ruleId: 'heuristics.ts.prometheus-prom-client.ast', code: 'HEURISTICS_PROMETHEUS_PROM_CLIENT_AST', message: 'AST heuristic detected Prometheus metrics instrumentation via prom-client.', pathCheck: (path) => path.startsWith('apps/backend/') },
|
|
512
|
-
{ detect: TS.hasPasswordHashingPattern, ruleId: 'heuristics.ts.password-hashing-bcrypt-salt-rounds-10.ast', code: 'HEURISTICS_PASSWORD_HASHING_BCRYPT_SALT_ROUNDS_10_AST', message: 'AST heuristic detected weak bcrypt salt rounds.', pathCheck: (path) => path.startsWith('apps/backend/') },
|
|
513
|
-
{ detect: TS.hasRateLimitingThrottlerPattern, ruleId: 'heuristics.ts.rate-limiting-throttler.ast', code: 'HEURISTICS_RATE_LIMITING_THROTTLER_AST', message: 'AST heuristic detected NestJS throttler rate limiting.', pathCheck: (path) => path.startsWith('apps/backend/') },
|
|
514
|
-
{ detect: TS.hasWinstonStructuredLoggerPattern, ruleId: 'heuristics.ts.winston-structured-json-logger.ast', code: 'HEURISTICS_WINSTON_STRUCTURED_JSON_LOGGER_AST', message: 'AST heuristic detected Winston structured JSON logger usage.', pathCheck: (path) => path.startsWith('apps/backend/') },
|
|
515
|
-
{ detect: TS.hasErrorLoggingFullContextPattern, ruleId: 'heuristics.ts.error-logging-full-context.ast', code: 'HEURISTICS_ERROR_LOGGING_FULL_CONTEXT_AST', message: 'AST heuristic detected backend error logging without full context.', pathCheck: (path) => path.startsWith('apps/backend/') },
|
|
516
413
|
{ detect: TS.hasLargeClassDeclaration, ruleId: 'heuristics.ts.god-class-large-class.ast', code: 'HEURISTICS_GOD_CLASS_LARGE_CLASS_AST', message: 'AST heuristic detected God Class candidate by mixed responsibility nodes in a single class declaration.' },
|
|
517
|
-
{ detect: TS.hasReactClassComponentUsage, locateLines: TS.findReactClassComponentLines, ruleId: 'heuristics.ts.react-class-component.ast', code: 'HEURISTICS_TS_REACT_CLASS_COMPONENT_AST', message: 'AST heuristic detected React class component usage in frontend production code where functional components are required.', pathCheck: isTypeScriptFrontendPath },
|
|
518
|
-
{ detect: TS.hasSingletonPattern, ruleId: 'heuristics.ts.singleton-pattern.ast', code: 'HEURISTICS_SINGLETON_PATTERN_AST', message: 'AST heuristic detected singleton pattern usage in a class declaration.' },
|
|
519
414
|
{ detect: TS.hasRecordStringUnknownType, locateLines: TS.findRecordStringUnknownTypeLines, ruleId: 'common.types.record_unknown_requires_type', code: 'COMMON_TYPES_RECORD_UNKNOWN_REQUIRES_TYPE_AST', message: 'AST heuristic detected Record<string, unknown> without explicit value union.' },
|
|
520
415
|
{ detect: TS.hasUnknownWithoutGuard, locateLines: TS.findUnknownWithoutGuardLines, ruleId: 'common.types.unknown_without_guard', code: 'COMMON_TYPES_UNKNOWN_WITHOUT_GUARD_AST', message: 'AST heuristic detected unknown usage without explicit guard evidence.', pathCheck: isTypeScriptDomainOrApplicationPath },
|
|
521
416
|
{ detect: TS.hasUndefinedInBaseTypeUnion, locateLines: TS.findUndefinedInBaseTypeUnionLines, ruleId: 'common.types.undefined_in_base_type', code: 'COMMON_TYPES_UNDEFINED_IN_BASE_TYPE_AST', message: 'AST heuristic detected undefined inside base-type unions.' },
|
|
@@ -711,10 +606,7 @@ const textDetectorRegistry: ReadonlyArray<TextDetectorRegistryEntry> = [
|
|
|
711
606
|
{ platform: 'ios', pathCheck: isIOSSwiftPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftObservableObjectUsage, ruleId: 'heuristics.ios.observable-object.ast', code: 'HEURISTICS_IOS_OBSERVABLE_OBJECT_AST', message: 'AST heuristic detected ObservableObject usage.' },
|
|
712
607
|
{ platform: 'ios', pathCheck: isIOSSwiftPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftLegacySwiftUiObservableWrapperUsage, ruleId: 'heuristics.ios.legacy-swiftui-observable-wrapper.ast', code: 'HEURISTICS_IOS_LEGACY_SWIFTUI_OBSERVABLE_WRAPPER_AST', message: 'AST heuristic detected @StateObject/@ObservedObject usage in a modern SwiftUI path.' },
|
|
713
608
|
{ platform: 'ios', pathCheck: isIOSSwiftPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftPassedValueStateWrapperUsage, ruleId: 'heuristics.ios.passed-value-state-wrapper.ast', code: 'HEURISTICS_IOS_PASSED_VALUE_STATE_WRAPPER_AST', message: 'AST heuristic detected a passed value stored as @State/@StateObject via init wrapper ownership.' },
|
|
714
|
-
{ platform: 'ios', pathCheck: isIOSSwiftPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftStateWrapperWithoutPrivateUsage, ruleId: 'heuristics.ios.swiftui.state-wrapper-private.ast', code: 'HEURISTICS_IOS_SWIFTUI_STATE_WRAPPER_PRIVATE_AST', message: 'AST heuristic detected @State/@StateObject usage in a SwiftUI View without private visibility.' },
|
|
715
609
|
{ platform: 'ios', pathCheck: isIOSPresentationPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftForEachIndicesUsage, ruleId: 'heuristics.ios.foreach-indices.ast', code: 'HEURISTICS_IOS_FOREACH_INDICES_AST', message: 'AST heuristic detected ForEach(...indices...) usage where stable element identity may be preferred.' },
|
|
716
|
-
{ platform: 'ios', pathCheck: isIOSPresentationPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftInlineFilteringInForEachUsage, ruleId: 'heuristics.ios.swiftui.inline-filtering-in-foreach.ast', code: 'HEURISTICS_IOS_SWIFTUI_INLINE_FILTERING_IN_FOREACH_AST', message: 'AST heuristic detected inline filtering inside ForEach; prefilter and cache before rendering.' },
|
|
717
|
-
{ platform: 'ios', pathCheck: isIOSPresentationPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftExplicitColorStaticMemberUsage, ruleId: 'heuristics.ios.swiftui.explicit-color-static-member.ast', code: 'HEURISTICS_IOS_SWIFTUI_EXPLICIT_COLOR_STATIC_MEMBER_AST', message: 'AST heuristic detected explicit Color static member lookup where contextual .color style is preferred.' },
|
|
718
610
|
{ platform: 'ios', pathCheck: isIOSApplicationOrPresentationPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftContainsUserFilterUsage, ruleId: 'heuristics.ios.contains-user-filter.ast', code: 'HEURISTICS_IOS_CONTAINS_USER_FILTER_AST', message: 'AST heuristic detected contains() in a user-facing filter where localizedStandardContains() may be preferred.' },
|
|
719
611
|
{ platform: 'ios', pathCheck: isIOSPresentationPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftGeometryReaderUsage, ruleId: 'heuristics.ios.geometryreader.ast', code: 'HEURISTICS_IOS_GEOMETRYREADER_AST', message: 'AST heuristic detected GeometryReader usage that may be replaceable with modern layout APIs.' },
|
|
720
612
|
{ platform: 'ios', pathCheck: isIOSPresentationPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftFontWeightBoldUsage, ruleId: 'heuristics.ios.font-weight-bold.ast', code: 'HEURISTICS_IOS_FONT_WEIGHT_BOLD_AST', message: 'AST heuristic detected fontWeight(.bold) usage where bold() may be preferred.' },
|
|
@@ -744,82 +636,6 @@ const textDetectorRegistry: ReadonlyArray<TextDetectorRegistryEntry> = [
|
|
|
744
636
|
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasKotlinThreadSleepCall, ruleId: 'heuristics.android.thread-sleep.ast', code: 'HEURISTICS_ANDROID_THREAD_SLEEP_AST', message: 'AST heuristic detected Thread.sleep usage in production Kotlin code.' },
|
|
745
637
|
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasKotlinGlobalScopeUsage, ruleId: 'heuristics.android.globalscope.ast', code: 'HEURISTICS_ANDROID_GLOBAL_SCOPE_AST', message: 'AST heuristic detected GlobalScope coroutine usage in production Kotlin code.' },
|
|
746
638
|
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasKotlinRunBlockingUsage, ruleId: 'heuristics.android.run-blocking.ast', code: 'HEURISTICS_ANDROID_RUN_BLOCKING_AST', message: 'AST heuristic detected runBlocking usage in production Kotlin code.' },
|
|
747
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidCoroutineCallbackUsage, ruleId: 'heuristics.android.coroutines-async-await-no-callbacks.ast', code: 'HEURISTICS_ANDROID_COROUTINES_ASYNC_AWAIT_NO_CALLBACKS_AST', message: 'AST heuristic detected callback-based asynchronous work in Android production code where coroutines or Flow should be used.' },
|
|
748
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidAsyncAwaitParallelismUsage, ruleId: 'heuristics.android.async-await-paralelismo.ast', code: 'HEURISTICS_ANDROID_ASYNC_AWAIT_PARALELISMO_AST', message: 'AST heuristic detected async/await parallelism in Android production code.' },
|
|
749
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidSuspendFunctionsApiServiceUsage, ruleId: 'heuristics.android.suspend-functions-en-api-service.ast', code: 'HEURISTICS_ANDROID_SUSPEND_FUNCTIONS_EN_API_SERVICE_AST', message: 'AST heuristic detected suspend functions in Android API service production code.' },
|
|
750
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidSuspendFunctionsAsyncUsage, ruleId: 'heuristics.android.suspend-functions-para-operaciones-async.ast', code: 'HEURISTICS_ANDROID_SUSPEND_FUNCTIONS_PARA_OPERACIONES_ASYNC_AST', message: 'AST heuristic detected suspend functions in Android production code where async operations should remain explicit.' },
|
|
751
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidDaoSuspendFunctionsUsage, ruleId: 'heuristics.android.dao-data-access-objects-con-suspend-functions.ast', code: 'HEURISTICS_ANDROID_DAO_DATA_ACCESS_OBJECTS_CON_SUSPEND_FUNCTIONS_AST', message: 'AST heuristic detected suspend functions in Android DAO production code.' },
|
|
752
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidTransactionUsage, ruleId: 'heuristics.android.transaction-para-operaciones-multi-query.ast', code: 'HEURISTICS_ANDROID_TRANSACTION_PARA_OPERACIONES_MULTI_QUERY_AST', message: 'AST heuristic detected @Transaction usage in Android DAO production code.' },
|
|
753
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidStateFlowUsage, ruleId: 'heuristics.android.stateflow-estado-mutable-observable.ast', code: 'HEURISTICS_ANDROID_STATEFLOW_ESTADO_MUTABLE_OBSERVABLE_AST', message: 'AST heuristic detected StateFlow usage in Android ViewModel production code where observable state should remain explicit.' },
|
|
754
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidSingleSourceOfTruthUsage, ruleId: 'heuristics.android.single-source-of-truth-viewmodel-es-la-fuente.ast', code: 'HEURISTICS_ANDROID_SINGLE_SOURCE_OF_TRUTH_VIEWMODEL_ES_LA_FUENTE_AST', message: 'AST heuristic detected single source of truth state exposure in Android ViewModel production code where observable state should remain explicit and owned by one ViewModel.' },
|
|
755
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidSharedFlowUsage, ruleId: 'heuristics.android.sharedflow-hot-stream-puede-no-tener-valor-para-eventos.ast', code: 'HEURISTICS_ANDROID_SHAREDFLOW_HOT_STREAM_PUEDE_NO_TENER_VALOR_PARA_EVENTOS_AST', message: 'AST heuristic detected SharedFlow usage in Android production code where events should remain explicit.' },
|
|
756
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidFlowBuilderUsage, ruleId: 'heuristics.android.flow-builders-flow-emit-flowof-asflow.ast', code: 'HEURISTICS_ANDROID_FLOW_BUILDERS_FLOW_EMIT_FLOWOF_ASFLOW_AST', message: 'AST heuristic detected Flow builder usage in Android production code where reactive streams should remain explicit.' },
|
|
757
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidFlowCollectUsage, ruleId: 'heuristics.android.collect-terminal-operator-para-consumir-flow.ast', code: 'HEURISTICS_ANDROID_COLLECT_TERMINAL_OPERATOR_PARA_CONSUMIR_FLOW_AST', message: 'AST heuristic detected Flow terminal operator usage in Android production code where streams should be consumed explicitly.' },
|
|
758
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidCollectAsStateUsage, ruleId: 'heuristics.android.collect-as-state-consumir-flow-en-compose.ast', code: 'HEURISTICS_ANDROID_COLLECT_AS_STATE_CONSUMIR_FLOW_EN_COMPOSE_AST', message: 'AST heuristic detected collectAsState usage in Android Compose production code where Flow should be observed as UI state.' },
|
|
759
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidRememberUsage, ruleId: 'heuristics.android.remember-evitar-recrear-objetos.ast', code: 'HEURISTICS_ANDROID_REMEMBER_EVITAR_RECREAR_OBJETOS_AST', message: 'AST heuristic detected remember usage in Android Compose production code where objects or values should not be recreated on every recomposition.' },
|
|
760
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidRememberUsage, ruleId: 'heuristics.android.remember-para-mantener-estado-entre-recomposiciones.ast', code: 'HEURISTICS_ANDROID_REMEMBER_PARA_MANTENER_ESTADO_ENTRE_RECOMPOSICIONES_AST', message: 'AST heuristic detected remember usage in Android Compose production code where state should remain stable across recompositions.' },
|
|
761
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidRepositoryPatternUsage, ruleId: 'heuristics.android.repository-pattern-abstraer-acceso-a-datos.ast', code: 'HEURISTICS_ANDROID_REPOSITORY_PATTERN_ABSTRAER_ACCESO_A_DATOS_AST', message: 'AST heuristic detected repository abstraction in Android production code where data access should remain behind a stable boundary.' },
|
|
762
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidDerivedStateOfUsage, ruleId: 'heuristics.android.derivedstateof-ca-lculos-caros-solo-cuando-cambia-input.ast', code: 'HEURISTICS_ANDROID_DERIVEDSTATEOF_CALCULOS_CAROS_SOLO_CUANDO_CAMBIA_INPUT_AST', message: 'AST heuristic detected derivedStateOf usage in Android Compose production code where expensive derived values should only recompute when input changes.' },
|
|
763
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidDerivedStateOfUsage, ruleId: 'heuristics.android.derivedstateof-ca-lculos-derivados-de-state.ast', code: 'HEURISTICS_ANDROID_DERIVEDSTATEOF_CALCULOS_DERIVADOS_DE_STATE_AST', message: 'AST heuristic detected derivedStateOf usage in Android Compose production code where state-derived values should stay explicit and local to Compose.' },
|
|
764
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidLaunchedEffectUsage, ruleId: 'heuristics.android.launchedeffect-side-effects-con-lifecycle.ast', code: 'HEURISTICS_ANDROID_LAUNCHEDEFFECT_SIDE_EFFECTS_CON_LIFECYCLE_AST', message: 'AST heuristic detected LaunchedEffect usage in Android Compose production code where lifecycle-bound side effects should remain explicit.' },
|
|
765
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidLaunchedEffectKeysUsage, ruleId: 'heuristics.android.launchedeffect-keys-controlar-cuando-se-relanza-effect.ast', code: 'HEURISTICS_ANDROID_LAUNCHEDEFFECT_KEYS_CONTROLAR_CUANDO_SE_RELANZA_EFFECT_AST', message: 'AST heuristic detected LaunchedEffect keys usage in Android Compose production code where relaunch keys should remain explicit and stable.' },
|
|
766
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidDisposableEffectUsage, ruleId: 'heuristics.android.disposableeffect-cleanup-cuando-composable-sale-de-composicio-n.ast', code: 'HEURISTICS_ANDROID_DISPOSABLE_EFFECT_CLEANUP_CUANDO_COMPOSABLE_SALE_DE_COMPOSICIO_N_AST', message: 'AST heuristic detected DisposableEffect usage in Android Compose production code where cleanup should run when the composable leaves composition.' },
|
|
767
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidPreviewUsage, ruleId: 'heuristics.android.preview-preview-para-ver-ui-sin-correr-app.ast', code: 'HEURISTICS_ANDROID_PREVIEW_PREVIEW_PARA_VER_UI_SIN_CORRER_APP_AST', message: 'AST heuristic detected @Preview usage in Android Compose production code where UI should be inspectable without running the app.' },
|
|
768
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidAdaptiveLayoutsUsage, ruleId: 'heuristics.android.adaptive-layouts-responsive-design-windowsizeclass.ast', code: 'HEURISTICS_ANDROID_ADAPTIVE_LAYOUTS_RESPONSIVE_DESIGN_WINDOW_SIZE_CLASS_AST', message: 'AST heuristic detected WindowSizeClass usage in Android Compose production code where the layout should adapt to the available window size.' },
|
|
769
|
-
{ platform: 'android', pathCheck: isAndroidSourcePath, excludePaths: [isKotlinTestPath, isJavaTestPath], detect: TextAndroid.hasAndroidExistingStructureUsage, ruleId: 'heuristics.android.analizar-estructura-existente-mo-dulos-interfaces-dependencias-gradle.ast', code: 'HEURISTICS_ANDROID_ANALIZAR_ESTRUCTURA_EXISTENTE_MO_DULOS_INTERFACES_DEPENDENCIAS_GRADLE_AST', message: 'AST heuristic detected Android structure usage where existing modules, interfaces and dependencies should be reviewed before introducing changes.' },
|
|
770
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidThemeUsage, ruleId: 'heuristics.android.theme-color-scheme-typography-shapes.ast', code: 'HEURISTICS_ANDROID_THEME_COLOR_SCHEME_TYPOGRAPHY_SHAPES_AST', message: 'AST heuristic detected MaterialTheme usage in Android Compose production code where theme configuration should remain explicit.' },
|
|
771
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidDarkThemeUsage, ruleId: 'heuristics.android.dark-theme-soportar-desde-di-a-1-issystemindarktheme.ast', code: 'HEURISTICS_ANDROID_DARK_THEME_SOPORTAR_DESDE_DI_A_1_ISSYSTEMINDARKTHEME_AST', message: 'AST heuristic detected explicit dark theme support in Android Compose production code where the UI should respect the system color scheme from day one.' },
|
|
772
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidTextScalingUsage, ruleId: 'heuristics.android.text-scaling-soportar-font-scaling-del-sistema.ast', code: 'HEURISTICS_ANDROID_TEXT_SCALING_SOPORTAR_FONT_SCALING_DEL_SISTEMA_AST', message: 'AST heuristic detected text scaling support in Android Compose production code where the UI should respect the system font scale and remain readable with accessibility settings.' },
|
|
773
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidAccessibilityUsage, ruleId: 'heuristics.android.accessibility-semantics-contentdescription.ast', code: 'HEURISTICS_ANDROID_ACCESSIBILITY_SEMANTICS_CONTENTDESCRIPTION_AST', message: 'AST heuristic detected accessibility semantics/contentDescription usage in Android Compose production code where the UI should remain accessible to screen readers and assistive technologies.' },
|
|
774
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidContentDescriptionUsage, ruleId: 'heuristics.android.contentdescription-para-ima-genes-y-botones.ast', code: 'HEURISTICS_ANDROID_CONTENTDESCRIPTION_PARA_IMAGENES_Y_BOTONES_AST', message: 'AST heuristic detected contentDescription usage in Android Compose production code where images and buttons should remain accessible to screen readers and assistive technologies.' },
|
|
775
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidTalkBackUsage, ruleId: 'heuristics.android.talkback-screen-reader-de-android.ast', code: 'HEURISTICS_ANDROID_TALKBACK_SCREEN_READER_DE_ANDROID_AST', message: 'AST heuristic detected TalkBack-related accessibility usage in Android Compose production code where the UI should remain accessible to screen readers.' },
|
|
776
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidRecompositionUsage, ruleId: 'heuristics.android.recomposition-composables-deben-ser-idempotentes.ast', code: 'HEURISTICS_ANDROID_RECOMPOSITION_COMPOSABLES_DEBEN_SER_IDEMPOTENTES_AST', message: 'AST heuristic detected non-idempotent Compose recomposition behavior in Android production code where composables should remain pure during recomposition.' },
|
|
777
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidUiStateUsage, ruleId: 'heuristics.android.uistate-sealed-class-loading-success-error-states.ast', code: 'HEURISTICS_ANDROID_UISTATE_SEALED_CLASS_LOADING_SUCCESS_ERROR_STATES_AST', message: 'AST heuristic detected UiState sealed class usage in Android production code where loading, success, and error states should stay explicit.' },
|
|
778
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidUseCaseUsage, ruleId: 'heuristics.android.use-cases-lo-gica-de-negocio-encapsulada.ast', code: 'HEURISTICS_ANDROID_USE_CASES_LOGICA_DE_NEGOCIO_ENCAPSULADA_AST', message: 'AST heuristic detected Android UseCase usage in production code where business logic should stay encapsulated.' },
|
|
779
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidStateHoistingUsage, ruleId: 'heuristics.android.state-hoisting-elevar-estado-al-nivel-apropiado.ast', code: 'HEURISTICS_ANDROID_STATE_HOISTING_ELEVAR_ESTADO_AL_NIVEL_APROPIADO_AST', message: 'AST heuristic detected state hoisting issues in Android Compose production code where UI state should be elevated to the appropriate owner.' },
|
|
780
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidViewModelUsage, ruleId: 'heuristics.android.viewmodel-androidx-lifecycle-viewmodel.ast', code: 'HEURISTICS_ANDROID_VIEWMODEL_ANDROIDX_LIFECYCLE_VIEWMODEL_AST', message: 'AST heuristic detected AndroidX ViewModel usage in Android production code.' },
|
|
781
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidViewModelUsage, ruleId: 'heuristics.android.viewmodel-sobrevive-configuration-changes.ast', code: 'HEURISTICS_ANDROID_VIEWMODEL_SOBREVIVE_CONFIGURATION_CHANGES_AST', message: 'AST heuristic detected AndroidX ViewModel usage in Android production code that should survive configuration changes.' },
|
|
782
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasKotlinForceUnwrapUsage, ruleId: 'heuristics.android.force-unwrap.ast', code: 'HEURISTICS_ANDROID_FORCE_UNWRAP_AST', message: 'AST heuristic detected Kotlin force unwrap (!!) usage in production code.' },
|
|
783
|
-
{ platform: 'android', pathCheck: isAndroidJavaPath, excludePaths: [isJavaTestPath], detect: TextAndroid.hasAndroidJavaSourceCode, ruleId: 'heuristics.android.java-source.ast', code: 'HEURISTICS_ANDROID_JAVA_SOURCE_AST', message: 'AST heuristic detected Java source in Android production code where Kotlin is required for new code.' },
|
|
784
|
-
{ platform: 'android', pathCheck: isAndroidSourcePath, excludePaths: [isKotlinTestPath, isJavaTestPath], detect: TextAndroid.hasAndroidAsyncTaskUsage, ruleId: 'heuristics.android.asynctask-deprecated.ast', code: 'HEURISTICS_ANDROID_ASYNCTASK_DEPRECATED_AST', message: 'AST heuristic detected AsyncTask usage in Android production code where Coroutines are required.' },
|
|
785
|
-
{ platform: 'android', pathCheck: isAndroidSourcePath, excludePaths: [isKotlinTestPath, isJavaTestPath], detect: TextAndroid.hasAndroidFindViewByIdUsage, ruleId: 'heuristics.android.findviewbyid.ast', code: 'HEURISTICS_ANDROID_FINDVIEWBYID_AST', message: 'AST heuristic detected findViewById usage in Android production code where View Binding or Compose is required.' },
|
|
786
|
-
{ platform: 'android', pathCheck: isAndroidSourcePath, excludePaths: [isKotlinTestPath, isJavaTestPath], detect: TextAndroid.hasAndroidRxJavaUsage, ruleId: 'heuristics.android.rxjava-new-code.ast', code: 'HEURISTICS_ANDROID_RXJAVA_NEW_CODE_AST', message: 'AST heuristic detected RxJava usage in Android production code where Flow is required for new code.' },
|
|
787
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidDispatcherUsage, ruleId: 'heuristics.android.dispatchers-main-ui-io-network-disk-default-cpu.ast', code: 'HEURISTICS_ANDROID_DISPATCHERS_MAIN_UI_IO_NETWORK_DISK_DEFAULT_CPU_AST', message: 'AST heuristic detected explicit Dispatchers.Main/IO/Default usage in Android production code where dispatcher selection must remain intentional.' },
|
|
788
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidWithContextUsage, ruleId: 'heuristics.android.withcontext-change-dispatcher.ast', code: 'HEURISTICS_ANDROID_WITHCONTEXT_CHANGE_DISPATCHER_AST', message: 'AST heuristic detected withContext usage in Android production code where dispatcher switching is intentional.' },
|
|
789
|
-
{ platform: 'android', pathCheck: isAndroidSourcePath, excludePaths: [isKotlinTestPath, isJavaTestPath], detect: TextAndroid.hasAndroidNoConsoleLogUsage, ruleId: 'heuristics.android.no-console-log.ast', code: 'HEURISTICS_ANDROID_NO_CONSOLE_LOG_AST', message: 'AST heuristic detected Android logging usage in production code without a debug-only guard.' },
|
|
790
|
-
{ platform: 'android', pathCheck: isAndroidSourcePath, excludePaths: [isKotlinTestPath, isJavaTestPath], detect: TextAndroid.hasAndroidTimberUsage, ruleId: 'heuristics.android.timber-logging-library.ast', code: 'HEURISTICS_ANDROID_TIMBER_LOGGING_LIBRARY_AST', message: 'AST heuristic detected Timber logging usage in Android production code.' },
|
|
791
|
-
{ platform: 'android', pathCheck: isAndroidSourcePath, excludePaths: [isKotlinTestPath, isJavaTestPath], detect: TextAndroid.hasAndroidTouchTargetsUsage, ruleId: 'heuristics.android.touch-targets-mi-nimo-48dp.ast', code: 'HEURISTICS_ANDROID_TOUCH_TARGETS_MI_NIMO_48DP_AST', message: 'AST heuristic detected minimum touch target usage in Android production Compose code.' },
|
|
792
|
-
{ platform: 'android', pathCheck: isAndroidSourcePath, excludePaths: [isKotlinTestPath, isJavaTestPath], detect: TextAndroid.hasAndroidBuildConfigConstantUsage, ruleId: 'heuristics.android.buildconfig-constantes-en-tiempo-de-compilacio-n.ast', code: 'HEURISTICS_ANDROID_BUILDCONFIG_CONSTANTES_EN_TIEMPO_DE_COMPILACION_AST', message: 'AST heuristic detected Android BuildConfig constant usage in production code.' },
|
|
793
|
-
{ platform: 'android', pathCheck: isAndroidSourcePath, excludePaths: [isKotlinTestPath, isJavaTestPath], detect: TextAndroid.hasAndroidHardcodedStringUsage, ruleId: 'heuristics.android.hardcoded-strings.ast', code: 'HEURISTICS_ANDROID_HARDCODED_STRINGS_AST', message: 'AST heuristic detected hardcoded string literal usage in Android production code where strings.xml should be used.' },
|
|
794
|
-
{ platform: 'android', pathCheck: isAndroidLocalizedStringsXmlPath, excludePaths: [], detect: TextAndroid.hasAndroidStringsXmlUsage, ruleId: 'heuristics.android.localization-strings-xml-por-idioma-values-es-values-en.ast', code: 'HEURISTICS_ANDROID_LOCALIZATION_STRINGS_XML_POR_IDIOMA_VALUES_ES_VALUES_EN_AST', message: 'AST heuristic detected localized strings.xml resources in Android production code where language-specific text should remain in values-*/strings.xml.' },
|
|
795
|
-
{ platform: 'android', pathCheck: isAndroidLocalizedStringsXmlPath, excludePaths: [], detect: TextAndroid.hasAndroidStringFormattingUsage, ruleId: 'heuristics.android.string-formatting-1-s-2-d-para-argumentos.ast', code: 'HEURISTICS_ANDROID_STRING_FORMATTING_1_S_2_D_PARA_ARGUMENTOS_AST', message: 'AST heuristic detected positional string formatting placeholders in Android strings.xml resources where argument order should remain explicit and translation-safe.' },
|
|
796
|
-
{ platform: 'android', pathCheck: isAndroidLocalizedPluralsXmlPath, excludePaths: [], detect: TextAndroid.hasAndroidPluralsXmlUsage, ruleId: 'heuristics.android.plurals-values-plurals-xml.ast', code: 'HEURISTICS_ANDROID_PLURALS_VALUES_PLURALS_XML_AST', message: 'AST heuristic detected plurals.xml resources in Android production code where quantity strings should remain explicit.' },
|
|
797
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidSingletonUsage, ruleId: 'heuristics.android.no-singleton.ast', code: 'HEURISTICS_ANDROID_NO_SINGLETON_AST', message: 'AST heuristic detected Kotlin singleton object or companion singleton holder usage in Android production code where Hilt or Dagger DI should be used.' },
|
|
798
|
-
{ platform: 'android', pathCheck: isAndroidGradlePath, excludePaths: [], detect: TextAndroid.hasAndroidHiltDependencyUsage, ruleId: 'heuristics.android.hilt-com-google-dagger-hilt-android.ast', code: 'HEURISTICS_ANDROID_HILT_COM_GOOGLE_DAGGER_HILT_ANDROID_AST', message: 'AST heuristic detected Hilt Gradle dependency usage in Android build files.' },
|
|
799
|
-
{ platform: 'android', pathCheck: isAndroidInstrumentedTestPath, excludePaths: [], detect: TextAndroid.hasAndroidInstrumentedTestUsage, ruleId: 'heuristics.android.androidtest-instrumented-tests-device-emulator.ast', code: 'HEURISTICS_ANDROID_ANDROIDTEST_INSTRUMENTED_TESTS_DEVICE_EMULATOR_AST', message: 'AST heuristic detected Android instrumented tests in androidTest/ where device/emulator coverage should remain explicit.' },
|
|
800
|
-
{ platform: 'android', pathCheck: isKotlinTestPath, excludePaths: [], detect: TextAndroid.hasAndroidAaaPatternUsage, ruleId: 'heuristics.android.aaa-pattern-arrange-act-assert.ast', code: 'HEURISTICS_ANDROID_AAA_PATTERN_ARRANGE_ACT_ASSERT_AST', message: 'AST heuristic detected AAA test structure in Android tests where Arrange, Act, and Assert should remain explicit.' },
|
|
801
|
-
{ platform: 'android', pathCheck: isKotlinTestPath, excludePaths: [], detect: TextAndroid.hasAndroidGivenWhenThenUsage, ruleId: 'heuristics.android.given-when-then-bdd-style.ast', code: 'HEURISTICS_ANDROID_GIVEN_WHEN_THEN_BDD_STYLE_AST', message: 'AST heuristic detected Given-When-Then test structure in Android tests where behavior should remain explicit.' },
|
|
802
|
-
{ platform: 'android', pathCheck: isAndroidJvmTestPath, excludePaths: [], detect: TextAndroid.hasAndroidJvmUnitTestUsage, ruleId: 'heuristics.android.test-unit-tests-jvm.ast', code: 'HEURISTICS_ANDROID_TEST_UNIT_TESTS_JVM_AST', message: 'AST heuristic detected JVM unit tests in Android test/ source set where local unit tests should remain explicit.' },
|
|
803
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidHiltFrameworkUsage, ruleId: 'heuristics.android.hilt-di-framework-no-manual-factories.ast', code: 'HEURISTICS_ANDROID_HILT_DI_FRAMEWORK_NO_MANUAL_FACTORIES_AST', message: 'AST heuristic detected Hilt DI framework usage instead of manual factories in Android production code.' },
|
|
804
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidHiltAndroidAppUsage, ruleId: 'heuristics.android.hiltandroidapp-application-class.ast', code: 'HEURISTICS_ANDROID_HILTANDROIDAPP_APPLICATION_CLASS_AST', message: 'AST heuristic detected @HiltAndroidApp usage in Android production code.' },
|
|
805
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidAndroidEntryPointUsage, ruleId: 'heuristics.android.androidentrypoint-activity-fragment-viewmodel.ast', code: 'HEURISTICS_ANDROID_ANDROIDENTRYPOINT_ACTIVITY_FRAGMENT_VIEWMODEL_AST', message: 'AST heuristic detected @AndroidEntryPoint usage in Android production code.' },
|
|
806
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidInjectConstructorUsage, ruleId: 'heuristics.android.inject-constructor-constructor-injection.ast', code: 'HEURISTICS_ANDROID_INJECT_CONSTRUCTOR_CONSTRUCTOR_INJECTION_AST', message: 'AST heuristic detected @Inject constructor usage in Android production code.' },
|
|
807
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidModuleInstallInUsage, ruleId: 'heuristics.android.module-installin-provide-dependencies.ast', code: 'HEURISTICS_ANDROID_MODULE_INSTALLIN_PROVIDE_DEPENDENCIES_AST', message: 'AST heuristic detected @Module + @InstallIn usage in Android production code.' },
|
|
808
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidBindsUsage, ruleId: 'heuristics.android.binds-para-implementaciones-de-interfaces-ma-s-eficiente.ast', code: 'HEURISTICS_ANDROID_BINDS_PARA_IMPLEMENTACIONES_DE_INTERFACES_MA_S_EFICIENTE_AST', message: 'AST heuristic detected @Binds usage in Android production code where interface bindings should remain explicit and efficient.' },
|
|
809
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidProvidesUsage, ruleId: 'heuristics.android.provides-para-interfaces-o-third-party.ast', code: 'HEURISTICS_ANDROID_PROVIDES_PARA_INTERFACES_O_THIRD_PARTY_AST', message: 'AST heuristic detected @Provides usage in Android production code where interfaces or third-party bindings should remain explicit.' },
|
|
810
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidViewModelScopeUsage, ruleId: 'heuristics.android.viewmodelscope-scope-de-viewmodel-cancelado-automa-ticamente.ast', code: 'HEURISTICS_ANDROID_VIEWMODELSCOPE_SCOPE_DE_VIEWMODEL_CANCELADO_AUTOMATICAMENTE_AST', message: 'AST heuristic detected viewModelScope usage in Android production code where coroutine work should remain tied to the ViewModel lifecycle.' },
|
|
811
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidAnalyticsUsage, ruleId: 'heuristics.android.analytics-firebase-analytics-o-custom.ast', code: 'HEURISTICS_ANDROID_ANALYTICS_FIREBASE_ANALYTICS_O_CUSTOM_AST', message: 'AST heuristic detected analytics tracking usage in Android production code where app instrumentation should remain explicit.' },
|
|
812
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidProfilerUsage, ruleId: 'heuristics.android.android-profiler-cpu-memory-network-profiling.ast', code: 'HEURISTICS_ANDROID_ANDROID_PROFILER_CPU_MEMORY_NETWORK_PROFILING_AST', message: 'AST heuristic detected Android profiling instrumentation in production code where CPU, memory, and trace capture should remain explicit.' },
|
|
813
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidAppStartupUsage, ruleId: 'heuristics.android.app-startup-androidx-startup-para-lazy-init.ast', code: 'HEURISTICS_ANDROID_APP_STARTUP_ANDROIDX_STARTUP_PARA_LAZY_INIT_AST', message: 'AST heuristic detected androidx.startup Initializer usage in Android production code where app initialization should remain lazy and explicit.' },
|
|
814
|
-
{ platform: 'android', pathCheck: isAndroidInstrumentedTestPath, excludePaths: [], detect: TextAndroid.hasAndroidBaselineProfilesUsage, ruleId: 'heuristics.android.baseline-profiles-optimizacio-n-de-startup.ast', code: 'HEURISTICS_ANDROID_BASELINE_PROFILES_OPTIMIZACION_DE_STARTUP_AST', message: 'AST heuristic detected BaselineProfileRule usage in Android benchmark or instrumented test code where startup optimization should remain explicit.' },
|
|
815
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidSkipRecompositionUsage, ruleId: 'heuristics.android.skip-recomposition-para-metros-inmutables-o-estables.ast', code: 'HEURISTICS_ANDROID_SKIP_RECOMPOSITION_PARA_METROS_INMUTABLES_O_ESTABLES_AST', message: 'AST heuristic detected stable or immutable Compose parameters in Android production code where recomposition should be skippable.' },
|
|
816
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidStabilityUsage, ruleId: 'heuristics.android.stability-composables-estables-recomponen-menos.ast', code: 'HEURISTICS_ANDROID_STABILITY_COMPOSABLES_ESTABLES_RECOMPONEN_MENOS_AST', message: 'AST heuristic detected stable or immutable Compose model usage in Android production code where Compose recomposition should remain predictable.' },
|
|
817
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidViewModelScopedUsage, ruleId: 'heuristics.android.viewmodelscoped-para-dependencias-de-viewmodel.ast', code: 'HEURISTICS_ANDROID_VIEWMODELSCOPED_PARA_DEPENDENCIAS_DE_VIEWMODEL_AST', message: 'AST heuristic detected @ViewModelScoped usage in Android production code.' },
|
|
818
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidCoroutineTryCatchUsage, ruleId: 'heuristics.android.try-catch-manejo-de-errores-en-coroutines.ast', code: 'HEURISTICS_ANDROID_TRY_CATCH_MANEJO_DE_ERRORES_EN_COROUTINES_AST', message: 'AST heuristic detected try/catch usage in Android coroutine code where error handling must remain explicit.' },
|
|
819
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidSupervisorScopeUsage, ruleId: 'heuristics.android.supervisorscope-errores-no-cancelan-otros-jobs.ast', code: 'HEURISTICS_ANDROID_SUPERVISORSCOPE_ERRORES_NO_CANCELAN_OTROS_JOBS_AST', message: 'AST heuristic detected supervisorScope usage in Android coroutine code where sibling jobs should remain isolated.' },
|
|
820
|
-
{ platform: 'android', pathCheck: isAndroidKotlinPath, excludePaths: [isKotlinTestPath], detect: TextAndroid.hasAndroidWorkManagerBackgroundTaskUsage, ruleId: 'heuristics.android.workmanager-background-tasks.ast', code: 'HEURISTICS_ANDROID_WORKMANAGER_BACKGROUND_TASKS_AST', message: 'AST heuristic detected WorkManager worker usage in Android production code where background tasks should remain explicit.' },
|
|
821
|
-
{ platform: 'android', pathCheck: isAndroidVersionCatalogPath, excludePaths: [], detect: TextAndroid.hasAndroidVersionCatalogUsage, ruleId: 'heuristics.android.version-catalogs-libs-versions-toml-para-dependencias.ast', code: 'HEURISTICS_ANDROID_VERSION_CATALOGS_LIBS_VERSIONS_TOML_PARA_DEPENDENCIAS_AST', message: 'AST heuristic detected Android libs.versions.toml usage in dependency management files where version catalogs should remain explicit.' },
|
|
822
|
-
{ platform: 'android', pathCheck: isAndroidGradlePath, excludePaths: [], detect: TextAndroid.hasAndroidWorkManagerDependencyUsage, ruleId: 'heuristics.android.workmanager-androidx-work-work-runtime-ktx.ast', code: 'HEURISTICS_ANDROID_WORKMANAGER_ANDROIDX_WORK_WORK_RUNTIME_KTX_AST', message: 'AST heuristic detected WorkManager Gradle dependency usage in Android build files.' },
|
|
823
639
|
];
|
|
824
640
|
|
|
825
641
|
const extractWorkflowHeuristicFacts = (
|
|
@@ -903,30 +719,11 @@ export const extractHeuristicFacts = (
|
|
|
903
719
|
}
|
|
904
720
|
}
|
|
905
721
|
|
|
906
|
-
if (
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
createHeuristicFact({
|
|
912
|
-
ruleId: 'heuristics.ios.solid.srp.presentation-mixed-responsibilities.ast',
|
|
913
|
-
code: 'HEURISTICS_IOS_SOLID_SRP_XCTEST_MIXED_RESPONSIBILITIES_AST',
|
|
914
|
-
message:
|
|
915
|
-
'Semantic iOS SRP heuristic detected an XCTestCase suite mixing multiple responsibilities.',
|
|
916
|
-
filePath: fileFact.path,
|
|
917
|
-
lines: semanticTestSrpMatch.lines,
|
|
918
|
-
severity: 'CRITICAL',
|
|
919
|
-
primary_node: semanticTestSrpMatch.primary_node,
|
|
920
|
-
related_nodes: semanticTestSrpMatch.related_nodes,
|
|
921
|
-
why: semanticTestSrpMatch.why,
|
|
922
|
-
impact: semanticTestSrpMatch.impact,
|
|
923
|
-
expected_fix: semanticTestSrpMatch.expected_fix,
|
|
924
|
-
})
|
|
925
|
-
);
|
|
926
|
-
}
|
|
927
|
-
}
|
|
928
|
-
|
|
929
|
-
if (!isSwiftTestPath(fileFact.path)) {
|
|
722
|
+
if (
|
|
723
|
+
params.detectedPlatforms.ios?.detected &&
|
|
724
|
+
isIOSSwiftPath(fileFact.path) &&
|
|
725
|
+
!isSwiftTestPath(fileFact.path)
|
|
726
|
+
) {
|
|
930
727
|
if (isIOSApplicationOrPresentationPath(fileFact.path)) {
|
|
931
728
|
const semanticOcpMatch = TextIOS.findSwiftOpenClosedSwitchMatch(fileFact.content);
|
|
932
729
|
if (semanticOcpMatch) {
|
|
@@ -1048,7 +845,6 @@ export const extractHeuristicFacts = (
|
|
|
1048
845
|
})
|
|
1049
846
|
);
|
|
1050
847
|
}
|
|
1051
|
-
}
|
|
1052
848
|
}
|
|
1053
849
|
|
|
1054
850
|
if (
|
|
@@ -1079,7 +875,7 @@ export const extractHeuristicFacts = (
|
|
|
1079
875
|
|
|
1080
876
|
if (
|
|
1081
877
|
params.detectedPlatforms.android?.detected &&
|
|
1082
|
-
|
|
878
|
+
isAndroidApplicationOrPresentationPath(fileFact.path) &&
|
|
1083
879
|
!isKotlinTestPath(fileFact.path)
|
|
1084
880
|
) {
|
|
1085
881
|
const semanticOcpMatch = TextAndroid.findKotlinOpenClosedWhenMatch(fileFact.content);
|
|
@@ -1161,88 +957,6 @@ export const extractHeuristicFacts = (
|
|
|
1161
957
|
})
|
|
1162
958
|
);
|
|
1163
959
|
}
|
|
1164
|
-
|
|
1165
|
-
const semanticComposableMatch = TextAndroid.findAndroidComposableFunctionMatch(fileFact.content);
|
|
1166
|
-
if (semanticComposableMatch) {
|
|
1167
|
-
heuristicFacts.push(
|
|
1168
|
-
createHeuristicFact({
|
|
1169
|
-
ruleId: 'heuristics.android.composable-functions-composable-para-ui.ast',
|
|
1170
|
-
code: 'HEURISTICS_ANDROID_COMPOSABLE_FUNCTIONS_COMPOSABLE_PARA_UI_AST',
|
|
1171
|
-
message:
|
|
1172
|
-
'Semantic Android Compose heuristic detected @Composable UI functions in production code.',
|
|
1173
|
-
filePath: fileFact.path,
|
|
1174
|
-
lines: semanticComposableMatch.lines,
|
|
1175
|
-
severity: 'WARN',
|
|
1176
|
-
primary_node: semanticComposableMatch.primary_node,
|
|
1177
|
-
related_nodes: semanticComposableMatch.related_nodes,
|
|
1178
|
-
why: semanticComposableMatch.why,
|
|
1179
|
-
impact: semanticComposableMatch.impact,
|
|
1180
|
-
expected_fix: semanticComposableMatch.expected_fix,
|
|
1181
|
-
})
|
|
1182
|
-
);
|
|
1183
|
-
}
|
|
1184
|
-
|
|
1185
|
-
const semanticArgumentsMatch = TextAndroid.findAndroidArgumentsMatch(fileFact.content);
|
|
1186
|
-
if (semanticArgumentsMatch) {
|
|
1187
|
-
heuristicFacts.push(
|
|
1188
|
-
createHeuristicFact({
|
|
1189
|
-
ruleId: 'heuristics.android.arguments-pasar-datos-entre-pantallas.ast',
|
|
1190
|
-
code: 'HEURISTICS_ANDROID_ARGUMENTS_PASAR_DATOS_ENTRE_PANTALLAS_AST',
|
|
1191
|
-
message:
|
|
1192
|
-
'Semantic Android navigation heuristic detected explicit arguments passed between screens.',
|
|
1193
|
-
filePath: fileFact.path,
|
|
1194
|
-
lines: semanticArgumentsMatch.lines,
|
|
1195
|
-
severity: 'WARN',
|
|
1196
|
-
primary_node: semanticArgumentsMatch.primary_node,
|
|
1197
|
-
related_nodes: semanticArgumentsMatch.related_nodes,
|
|
1198
|
-
why: semanticArgumentsMatch.why,
|
|
1199
|
-
impact: semanticArgumentsMatch.impact,
|
|
1200
|
-
expected_fix: semanticArgumentsMatch.expected_fix,
|
|
1201
|
-
})
|
|
1202
|
-
);
|
|
1203
|
-
}
|
|
1204
|
-
|
|
1205
|
-
const semanticSingleActivityMatch = TextAndroid.findAndroidSingleActivityComposeShellMatch(
|
|
1206
|
-
fileFact.content
|
|
1207
|
-
);
|
|
1208
|
-
if (semanticSingleActivityMatch) {
|
|
1209
|
-
heuristicFacts.push(
|
|
1210
|
-
createHeuristicFact({
|
|
1211
|
-
ruleId: 'heuristics.android.single-activity-multiples-composables-fragments-no-activities.ast',
|
|
1212
|
-
code: 'HEURISTICS_ANDROID_SINGLE_ACTIVITY_MULTIPLES_COMPOSABLES_FRAGMENTS_NO_ACTIVITIES_AST',
|
|
1213
|
-
message:
|
|
1214
|
-
'Semantic Android Compose heuristic detected a single Activity compose shell in production code.',
|
|
1215
|
-
filePath: fileFact.path,
|
|
1216
|
-
lines: semanticSingleActivityMatch.lines,
|
|
1217
|
-
severity: 'WARN',
|
|
1218
|
-
primary_node: semanticSingleActivityMatch.primary_node,
|
|
1219
|
-
related_nodes: semanticSingleActivityMatch.related_nodes,
|
|
1220
|
-
why: semanticSingleActivityMatch.why,
|
|
1221
|
-
impact: semanticSingleActivityMatch.impact,
|
|
1222
|
-
expected_fix: semanticSingleActivityMatch.expected_fix,
|
|
1223
|
-
})
|
|
1224
|
-
);
|
|
1225
|
-
}
|
|
1226
|
-
|
|
1227
|
-
const semanticGodActivityMatch = TextAndroid.findAndroidGodActivityMatch(fileFact.content);
|
|
1228
|
-
if (semanticGodActivityMatch) {
|
|
1229
|
-
heuristicFacts.push(
|
|
1230
|
-
createHeuristicFact({
|
|
1231
|
-
ruleId: 'heuristics.android.god-activities-single-activity-composables.ast',
|
|
1232
|
-
code: 'HEURISTICS_ANDROID_GOD_ACTIVITIES_SINGLE_ACTIVITY_COMPOSABLES_AST',
|
|
1233
|
-
message:
|
|
1234
|
-
'Semantic Android Compose heuristic detected an Activity that concentrates Compose shell and composables in the same file.',
|
|
1235
|
-
filePath: fileFact.path,
|
|
1236
|
-
lines: semanticGodActivityMatch.lines,
|
|
1237
|
-
severity: 'ERROR',
|
|
1238
|
-
primary_node: semanticGodActivityMatch.primary_node,
|
|
1239
|
-
related_nodes: semanticGodActivityMatch.related_nodes,
|
|
1240
|
-
why: semanticGodActivityMatch.why,
|
|
1241
|
-
impact: semanticGodActivityMatch.impact,
|
|
1242
|
-
expected_fix: semanticGodActivityMatch.expected_fix,
|
|
1243
|
-
})
|
|
1244
|
-
);
|
|
1245
|
-
}
|
|
1246
960
|
}
|
|
1247
961
|
|
|
1248
962
|
// AST-based heuristics
|
|
@@ -1258,7 +972,7 @@ export const extractHeuristicFacts = (
|
|
|
1258
972
|
try {
|
|
1259
973
|
const ast = parse(fileFact.content, {
|
|
1260
974
|
sourceType: 'unambiguous',
|
|
1261
|
-
plugins: ['typescript', 'jsx'
|
|
975
|
+
plugins: ['typescript', 'jsx'],
|
|
1262
976
|
});
|
|
1263
977
|
|
|
1264
978
|
for (const entry of astDetectorRegistry) {
|
|
@@ -1270,26 +984,7 @@ export const extractHeuristicFacts = (
|
|
|
1270
984
|
}
|
|
1271
985
|
if (entry.detect(ast)) {
|
|
1272
986
|
const semanticMatch =
|
|
1273
|
-
entry.ruleId === 'heuristics.ts.
|
|
1274
|
-
? TS.findConsoleLogCallMatch(ast)
|
|
1275
|
-
: entry.ruleId === 'heuristics.ts.explicit-any.ast'
|
|
1276
|
-
? TS.findExplicitAnyTypeMatch(ast)
|
|
1277
|
-
: entry.ruleId === 'heuristics.ts.clean-architecture.ast'
|
|
1278
|
-
? TS.findCleanArchitectureMatch(ast)
|
|
1279
|
-
: entry.ruleId === 'heuristics.ts.production-mock.ast'
|
|
1280
|
-
? TS.findProductionMockCallMatch(ast)
|
|
1281
|
-
: entry.ruleId === 'heuristics.ts.exception-filter.ast'
|
|
1282
|
-
? TS.findExceptionFilterClassMatch(ast)
|
|
1283
|
-
: entry.ruleId === 'heuristics.ts.guards-useguards-jwtauthguard.ast'
|
|
1284
|
-
? TS.findGuardUseGuardsJwtAuthGuardMatch(ast)
|
|
1285
|
-
: entry.ruleId === 'heuristics.ts.interceptors-useinterceptors-logging-transform.ast'
|
|
1286
|
-
? TS.findUseInterceptorsLoggingTransformMatch(ast)
|
|
1287
|
-
: entry.ruleId === 'heuristics.ts.no-sensitive-log.ast'
|
|
1288
|
-
? TS.findSensitiveLogCallMatch(ast)
|
|
1289
|
-
: entry.ruleId === 'heuristics.ts.empty-catch.ast' ||
|
|
1290
|
-
entry.ruleId === 'common.error.empty_catch'
|
|
1291
|
-
? TS.findEmptyCatchClauseMatch(ast)
|
|
1292
|
-
: entry.ruleId === 'heuristics.ts.solid.srp.class-command-query-mix.ast'
|
|
987
|
+
entry.ruleId === 'heuristics.ts.solid.srp.class-command-query-mix.ast'
|
|
1293
988
|
? TS.findMixedCommandQueryClassMatch(ast)
|
|
1294
989
|
: entry.ruleId === 'heuristics.ts.solid.isp.interface-command-query-mix.ast'
|
|
1295
990
|
? TS.findMixedCommandQueryInterfaceMatch(ast)
|
|
@@ -1299,21 +994,9 @@ export const extractHeuristicFacts = (
|
|
|
1299
994
|
? TS.findOverrideMethodThrowingNotImplementedMatch(ast)
|
|
1300
995
|
: entry.ruleId === 'heuristics.ts.solid.dip.framework-import.ast'
|
|
1301
996
|
? TS.findFrameworkDependencyImportMatch(ast)
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
? TS.findSingletonPatternMatch(ast)
|
|
1306
|
-
: entry.ruleId === 'heuristics.ts.callback-hell.ast'
|
|
1307
|
-
? TS.findCallbackHellPatternMatch(ast)
|
|
1308
|
-
: entry.ruleId === 'heuristics.ts.magic-numbers.ast'
|
|
1309
|
-
? TS.findMagicNumberPatternMatch(ast)
|
|
1310
|
-
: entry.ruleId === 'heuristics.ts.hardcoded-values.ast'
|
|
1311
|
-
? TS.findHardcodedValuePatternMatch(ast)
|
|
1312
|
-
: entry.ruleId === 'heuristics.ts.env-default-fallback.ast'
|
|
1313
|
-
? TS.findEnvDefaultFallbackPatternMatch(ast)
|
|
1314
|
-
: entry.ruleId === 'heuristics.ts.god-class-large-class.ast'
|
|
1315
|
-
? TS.findLargeClassDeclarationMatch(ast)
|
|
1316
|
-
: undefined;
|
|
997
|
+
: entry.ruleId === 'heuristics.ts.solid.dip.concrete-instantiation.ast'
|
|
998
|
+
? TS.findConcreteDependencyInstantiationMatch(ast)
|
|
999
|
+
: undefined;
|
|
1317
1000
|
const lineLocator = entry.locateLines ?? astDetectorLineLocatorRegistry.get(entry.detect);
|
|
1318
1001
|
const lines = semanticMatch?.lines ?? lineLocator?.(ast);
|
|
1319
1002
|
heuristicFacts.push(
|
|
@@ -38,15 +38,8 @@ test('evaluateRules genera finding cuando la condicion coincide y usa code expli
|
|
|
38
38
|
code: 'BACKEND_FILE_MODIFIED',
|
|
39
39
|
message: 'Backend file modified.',
|
|
40
40
|
filePath: 'apps/backend/src/main.ts',
|
|
41
|
-
lines: undefined,
|
|
42
41
|
matchedBy: 'FileChange',
|
|
43
42
|
source: 'git',
|
|
44
|
-
blocking: true,
|
|
45
|
-
primary_node: undefined,
|
|
46
|
-
related_nodes: undefined,
|
|
47
|
-
why: undefined,
|
|
48
|
-
impact: undefined,
|
|
49
|
-
expected_fix: undefined,
|
|
50
43
|
});
|
|
51
44
|
});
|
|
52
45
|
|
|
@@ -23,7 +23,8 @@ type FindingTarget = {
|
|
|
23
23
|
expected_fix?: string;
|
|
24
24
|
};
|
|
25
25
|
|
|
26
|
-
const isBlockingSeverity = (
|
|
26
|
+
const isBlockingSeverity = (severity: RuleDefinition['severity']): boolean =>
|
|
27
|
+
severity === 'CRITICAL' || severity === 'ERROR';
|
|
27
28
|
|
|
28
29
|
export type EvaluateRulesCoverageResult = {
|
|
29
30
|
findings: ReadonlyArray<Finding>;
|