claude-git-hooks 1.3.0 → 1.4.1
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/CHANGELOG.md +27 -0
- package/README.md +142 -24
- package/bin/claude-hooks +33 -13
- package/package.json +2 -2
- package/templates/CLAUDE_ANALYSIS_PROMPT.md +44 -0
- package/templates/CLAUDE_ANALYSIS_PROMPT_SONAR.md +61 -0
- package/templates/CLAUDE_RESOLUTION_PROMPT.md +46 -0
- package/templates/pre-commit +123 -40
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,33 @@ Todos los cambios notables en este proyecto se documentarán en este archivo.
|
|
|
5
5
|
El formato está basado en [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
y este proyecto adhiere a [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.4.0] - 2025-08-29
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- 🎯 Prompts externalizados en archivos `.md` para facilitar personalización
|
|
12
|
+
- 🤖 Generación automática de prompt AI-friendly para resolución de problemas críticos
|
|
13
|
+
- 📝 Nuevos templates de prompts: `CLAUDE_ANALYSIS_PROMPT.md`, `CLAUDE_ANALYSIS_PROMPT_SONAR.md`, `CLAUDE_RESOLUTION_PROMPT.md`
|
|
14
|
+
- 🔍 Localización precisa en blockingIssues (archivo, línea, método, severidad)
|
|
15
|
+
- 📋 Archivo `claude_resolution_prompt.md` generado automáticamente con issues para resolver
|
|
16
|
+
- 🚀 Flag `--skip-auth` para omitir verificación de autenticación en instalación
|
|
17
|
+
- 📖 Ejemplos detallados de respuestas JSON con blocking issues en README
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
- 🏗️ Estandarización de `blockingIssues` a formato objeto (nunca strings)
|
|
21
|
+
- 📦 Separación de prompts del código para mayor mantenibilidad
|
|
22
|
+
- 🔧 Hook pre-commit simplificado sin fallbacks complejos
|
|
23
|
+
- 📁 Instalador actualizado para copiar todos los templates de prompts
|
|
24
|
+
|
|
25
|
+
### Fixed
|
|
26
|
+
- 🐛 Consistencia en el formato de respuesta JSON para ambos modos
|
|
27
|
+
- 🔧 Mejor manejo de errores cuando faltan archivos de configuración
|
|
28
|
+
|
|
29
|
+
### Technical
|
|
30
|
+
- 🏗️ Función `generate_resolution_prompt()` para crear prompts de resolución
|
|
31
|
+
- 📝 Templates de prompts con placeholders reemplazables
|
|
32
|
+
- 🎯 Estructura JSON estricta para blockingIssues con campos obligatorios
|
|
33
|
+
- 🔄 Instalación en modo force actualiza todos los templates
|
|
34
|
+
|
|
8
35
|
## [1.3.0] - 2025-08-28
|
|
9
36
|
|
|
10
37
|
### Added
|
package/README.md
CHANGED
|
@@ -10,6 +10,9 @@ Este directorio contiene un pre-commit hook que utiliza Claude CLI para revisar
|
|
|
10
10
|
- **`.gitattributes`** - Configuración para mantener line endings correctos
|
|
11
11
|
- **`.claude/CLAUDE_PRE_COMMIT.md`** - Pautas de evaluación formato estándar
|
|
12
12
|
- **`.claude/CLAUDE_PRE_COMMIT_SONAR.md`** - Pautas de evaluación formato SonarQube
|
|
13
|
+
- **`.claude/CLAUDE_ANALYSIS_PROMPT.md`** - Template de prompt para análisis estándar
|
|
14
|
+
- **`.claude/CLAUDE_ANALYSIS_PROMPT_SONAR.md`** - Template de prompt para análisis SonarQube
|
|
15
|
+
- **`.claude/CLAUDE_RESOLUTION_PROMPT.md`** - Template para generar prompt de resolución AI
|
|
13
16
|
|
|
14
17
|
## 🔧 Configuración Previa Importante
|
|
15
18
|
|
|
@@ -64,13 +67,19 @@ claude-hooks install
|
|
|
64
67
|
```
|
|
65
68
|
|
|
66
69
|
El comando `claude-hooks install` ahora incluye:
|
|
70
|
+
|
|
67
71
|
- ✅ Verificación completa de dependencias del sistema
|
|
68
72
|
- ✅ Instalación automática de paquetes faltantes (jq, curl)
|
|
69
73
|
- ✅ Configuración de Git (line endings WSL/Windows)
|
|
70
|
-
- ✅ Verificación de autenticación Claude con entretenimiento
|
|
74
|
+
- ✅ Verificación de autenticación Claude con entretenimiento (omitible con `--skip-auth`)
|
|
71
75
|
- ✅ Instalación de hooks y archivos de pautas
|
|
72
76
|
- ✅ Actualización automática de .gitignore con archivos de Claude
|
|
73
77
|
|
|
78
|
+
**Opciones de instalación:**
|
|
79
|
+
|
|
80
|
+
- `--force`: Reinstala aunque los hooks ya existan
|
|
81
|
+
- `--skip-auth`: Omite la verificación de autenticación de Claude (útil para CI/CD)
|
|
82
|
+
|
|
74
83
|
#### Añadir como Dependencia de Desarrollo
|
|
75
84
|
|
|
76
85
|
```bash
|
|
@@ -108,10 +117,14 @@ El comando `claude-hooks install` crea los siguientes archivos y directorios:
|
|
|
108
117
|
|
|
109
118
|
1. **`.git/hooks/pre-commit`** - Hook de análisis de código
|
|
110
119
|
2. **`.git/hooks/prepare-commit-msg`** - Hook de generación de mensajes
|
|
111
|
-
3. **`.
|
|
120
|
+
3. **`.git/hooks/check-version.sh`** - Script de verificación de versión
|
|
121
|
+
4. **`.claude/`** - Directorio para archivos de configuración
|
|
112
122
|
- `CLAUDE_PRE_COMMIT.md` - Pautas de evaluación estándar
|
|
113
123
|
- `CLAUDE_PRE_COMMIT_SONAR.md` - Pautas de evaluación SonarQube
|
|
114
|
-
|
|
124
|
+
- `CLAUDE_ANALYSIS_PROMPT.md` - Template de prompt para análisis estándar
|
|
125
|
+
- `CLAUDE_ANALYSIS_PROMPT_SONAR.md` - Template de prompt para análisis SonarQube
|
|
126
|
+
- `CLAUDE_RESOLUTION_PROMPT.md` - Template para prompt de resolución AI
|
|
127
|
+
5. **`.claude-analysis-mode`** - Archivo de preferencia de modo (creado al primer uso)
|
|
115
128
|
|
|
116
129
|
### Actualización automática de .gitignore
|
|
117
130
|
|
|
@@ -122,9 +135,11 @@ Durante la instalación, Claude Hooks actualiza automáticamente tu `.gitignore`
|
|
|
122
135
|
.claude/
|
|
123
136
|
.claude-analysis-mode
|
|
124
137
|
debug-claude-response.json
|
|
138
|
+
claude_resolution_prompt.md
|
|
125
139
|
```
|
|
126
140
|
|
|
127
141
|
Esto asegura que:
|
|
142
|
+
|
|
128
143
|
- Los archivos de configuración de Claude específicos del proyecto no se suban al repositorio
|
|
129
144
|
- Los archivos de debug temporales se ignoren
|
|
130
145
|
- Cada desarrollador pueda tener sus propias preferencias de análisis
|
|
@@ -144,17 +159,28 @@ Si no existe un `.gitignore`, se creará uno nuevo. Si ya existe, las entradas s
|
|
|
144
159
|
- **Estándar**: Formato clásico con score y recomendaciones detalladas
|
|
145
160
|
- **SonarQube**: Simula salida de SonarQube con Quality Gate, métricas y clasificación de issues
|
|
146
161
|
4. **Construye prompt inteligente**:
|
|
147
|
-
-
|
|
162
|
+
- Usa template de prompt desde `.claude/CLAUDE_ANALYSIS_PROMPT*.md`
|
|
163
|
+
- Lee las pautas desde `.claude/CLAUDE_PRE_COMMIT*.md`
|
|
148
164
|
- Incluye el diff completo para archivos nuevos
|
|
149
165
|
- Muestra solo cambios para archivos existentes
|
|
150
166
|
5. **Envía a Claude CLI para revisión**
|
|
151
|
-
6. **Procesa respuesta JSON**:
|
|
167
|
+
6. **Procesa respuesta JSON estructurada**:
|
|
168
|
+
- blockingIssues siempre como objetos con localización precisa
|
|
152
169
|
- En modo estándar: evalúa `approved`, `score`, `recommendations`
|
|
153
170
|
- En modo SonarQube: verifica `QUALITY_GATE`, muestra métricas y issues por severidad
|
|
154
171
|
7. **Decisión final**:
|
|
155
|
-
- Si hay problemas críticos
|
|
172
|
+
- Si hay problemas críticos → genera prompt AI de resolución y bloquea commit
|
|
156
173
|
- Si todo está bien → commit procede
|
|
157
174
|
|
|
175
|
+
#### 🤖 Generación de Prompt de Resolución AI
|
|
176
|
+
|
|
177
|
+
Cuando se detectan problemas críticos:
|
|
178
|
+
|
|
179
|
+
- Se genera automáticamente un archivo `claude_resolution_prompt.md`
|
|
180
|
+
- Contiene información estructurada y AI-friendly de todos los issues
|
|
181
|
+
- Incluye localización precisa (archivo, línea, método)
|
|
182
|
+
- Puede copiarse a otra instancia de Claude para resolución automática
|
|
183
|
+
|
|
158
184
|
### Hook prepare-commit-msg (Generación automática de mensajes)
|
|
159
185
|
|
|
160
186
|
1. **Se activa cuando el mensaje es**:
|
|
@@ -233,11 +259,13 @@ unset CLAUDE_ANALYSIS_MODE
|
|
|
233
259
|
#### 📋 Diferencias entre Modos
|
|
234
260
|
|
|
235
261
|
**Modo Estándar**:
|
|
262
|
+
|
|
236
263
|
- Análisis con puntuación del 1-10
|
|
237
264
|
- Recomendaciones detalladas por categoría
|
|
238
265
|
- Formato tradicional fácil de leer
|
|
239
266
|
|
|
240
267
|
**Modo SonarQube**:
|
|
268
|
+
|
|
241
269
|
- Quality Gate (PASSED/FAILED)
|
|
242
270
|
- Métricas: Reliability, Security, Maintainability
|
|
243
271
|
- Issues clasificados por severidad (Blocker, Critical, Major, Minor, Info)
|
|
@@ -266,13 +294,98 @@ DEBUG=1 git commit -m "mensaje"
|
|
|
266
294
|
|
|
267
295
|
## 📊 Formato de Respuesta
|
|
268
296
|
|
|
269
|
-
Claude responde con un JSON que incluye:
|
|
297
|
+
Claude responde con un JSON estructurado que incluye:
|
|
298
|
+
|
|
299
|
+
- `approved`: Si el commit es aprobado (boolean)
|
|
300
|
+
- `score`: Puntuación del 1-10 (integer)
|
|
301
|
+
- `blockingIssues`: Array de objetos con problemas críticos:
|
|
302
|
+
- `description`: Descripción del problema
|
|
303
|
+
- `file`: Archivo afectado
|
|
304
|
+
- `line`: Línea del problema
|
|
305
|
+
- `method`: Método o clase afectada
|
|
306
|
+
- `severity`: Severidad (critical, high, etc.)
|
|
307
|
+
- `recommendations`: Array de strings con sugerencias no bloqueantes
|
|
308
|
+
- `details`: Objeto con comentarios por categoría (security, performance, etc.)
|
|
309
|
+
|
|
310
|
+
### Ejemplos de Respuestas con Problemas Críticos
|
|
311
|
+
|
|
312
|
+
#### Modo Estándar - Commit Bloqueado
|
|
313
|
+
|
|
314
|
+
```json
|
|
315
|
+
{
|
|
316
|
+
"approved": false,
|
|
317
|
+
"score": 3,
|
|
318
|
+
"blockingIssues": [
|
|
319
|
+
{
|
|
320
|
+
"description": "SQL Injection vulnerability: concatenación directa de strings en query",
|
|
321
|
+
"file": "src/main/java/UserRepository.java",
|
|
322
|
+
"line": 45,
|
|
323
|
+
"method": "findUserByName",
|
|
324
|
+
"severity": "critical"
|
|
325
|
+
},
|
|
326
|
+
{
|
|
327
|
+
"description": "Posible NullPointerException: variable 'user' no validada",
|
|
328
|
+
"file": "src/main/java/UserService.java",
|
|
329
|
+
"line": 78,
|
|
330
|
+
"method": "processUser",
|
|
331
|
+
"severity": "high"
|
|
332
|
+
}
|
|
333
|
+
],
|
|
334
|
+
"recommendations": [
|
|
335
|
+
"Usar PreparedStatement en lugar de concatenación de strings",
|
|
336
|
+
"Agregar validación de null antes de acceder a propiedades"
|
|
337
|
+
]
|
|
338
|
+
}
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
#### Modo SonarQube - Quality Gate Failed
|
|
342
|
+
|
|
343
|
+
```json
|
|
344
|
+
{
|
|
345
|
+
"QUALITY_GATE": "FAILED",
|
|
346
|
+
"approved": false,
|
|
347
|
+
"score": 4,
|
|
348
|
+
"metrics": {
|
|
349
|
+
"reliability": "D",
|
|
350
|
+
"security": "E",
|
|
351
|
+
"maintainability": "C"
|
|
352
|
+
},
|
|
353
|
+
"issues": {
|
|
354
|
+
"blocker": 1,
|
|
355
|
+
"critical": 2,
|
|
356
|
+
"major": 3,
|
|
357
|
+
"minor": 1
|
|
358
|
+
},
|
|
359
|
+
"blockingIssues": [
|
|
360
|
+
{
|
|
361
|
+
"description": "Security Hotspot: Hardcoded credentials detected",
|
|
362
|
+
"file": "src/main/resources/application.yml",
|
|
363
|
+
"line": 23,
|
|
364
|
+
"method": "datasource.password",
|
|
365
|
+
"severity": "blocker"
|
|
366
|
+
},
|
|
367
|
+
{
|
|
368
|
+
"description": "Resource leak: Connection not closed in finally block",
|
|
369
|
+
"file": "src/main/java/DatabaseUtil.java",
|
|
370
|
+
"line": 112,
|
|
371
|
+
"method": "executeQuery",
|
|
372
|
+
"severity": "critical"
|
|
373
|
+
}
|
|
374
|
+
],
|
|
375
|
+
"details": [
|
|
376
|
+
{
|
|
377
|
+
"severity": "BLOCKER",
|
|
378
|
+
"type": "VULNERABILITY",
|
|
379
|
+
"file": "src/main/resources/application.yml",
|
|
380
|
+
"line": 23,
|
|
381
|
+
"message": "Never store passwords in plain text",
|
|
382
|
+
"rule": "java:S2068"
|
|
383
|
+
}
|
|
384
|
+
]
|
|
385
|
+
}
|
|
386
|
+
```
|
|
270
387
|
|
|
271
|
-
|
|
272
|
-
- `score`: Puntuación del 1-10
|
|
273
|
-
- `commitMessage`: Mensaje de commit generado (type, title, body)
|
|
274
|
-
- `recommendations`: Recomendaciones de mejora
|
|
275
|
-
- `blockingIssues`: Problemas que bloquean el commit
|
|
388
|
+
Cuando se detectan estos problemas críticos, se genera automáticamente un archivo `claude_resolution_prompt.md` con toda la información necesaria para que otra instancia de Claude pueda resolver los issues de forma eficiente.
|
|
276
389
|
|
|
277
390
|
## 🔄 Actualización y Gestión
|
|
278
391
|
|
|
@@ -395,11 +508,24 @@ Este problema suele ocurrir por conflictos de configuración de line endings:
|
|
|
395
508
|
|
|
396
509
|
## 📝 Personalización
|
|
397
510
|
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
511
|
+
### Archivos de Configuración en `.claude/`
|
|
512
|
+
|
|
513
|
+
#### Pautas de Evaluación
|
|
514
|
+
|
|
515
|
+
- **`CLAUDE_PRE_COMMIT.md`** - Criterios de evaluación para modo estándar
|
|
516
|
+
- **`CLAUDE_PRE_COMMIT_SONAR.md`** - Criterios para modo SonarQube
|
|
517
|
+
|
|
518
|
+
#### Templates de Prompts
|
|
401
519
|
|
|
402
|
-
|
|
520
|
+
- **`CLAUDE_ANALYSIS_PROMPT.md`** - Estructura del prompt de análisis estándar
|
|
521
|
+
- **`CLAUDE_ANALYSIS_PROMPT_SONAR.md`** - Estructura del prompt SonarQube
|
|
522
|
+
- **`CLAUDE_RESOLUTION_PROMPT.md`** - Template para generar prompts de resolución
|
|
523
|
+
|
|
524
|
+
Todos estos archivos son personalizables y específicos de tu proyecto. Puedes:
|
|
525
|
+
|
|
526
|
+
- Modificar los criterios de evaluación según estándares del equipo
|
|
527
|
+
- Ajustar la estructura de los prompts para obtener respuestas más precisas
|
|
528
|
+
- Personalizar el formato de salida del prompt de resolución
|
|
403
529
|
|
|
404
530
|
## 🔄 Arquitectura del Sistema
|
|
405
531
|
|
|
@@ -574,11 +700,3 @@ git commit -m "auto"
|
|
|
574
700
|
3. **Commit** tus cambios: `git commit -m "feat: nueva funcionalidad"`
|
|
575
701
|
4. **Push** al branch: `git push origin feature/nueva-funcionalidad`
|
|
576
702
|
5. **Abrir Pull Request**
|
|
577
|
-
|
|
578
|
-
### Roadmap
|
|
579
|
-
|
|
580
|
-
- [ ] Soporte para más lenguajes (Python, JavaScript, etc.)
|
|
581
|
-
- [ ] Configuración más granular por proyecto
|
|
582
|
-
- [ ] Integration con IDEs populares
|
|
583
|
-
- [ ] Métricas de uso y performance
|
|
584
|
-
- [ ] Tests automatizados
|
package/bin/claude-hooks
CHANGED
|
@@ -339,6 +339,7 @@ async function install(args) {
|
|
|
339
339
|
}
|
|
340
340
|
|
|
341
341
|
const isForce = args.includes('--force');
|
|
342
|
+
const skipAuth = args.includes('--skip-auth');
|
|
342
343
|
|
|
343
344
|
if (isForce) {
|
|
344
345
|
info('Instalando Claude Git Hooks (modo force)...');
|
|
@@ -364,7 +365,7 @@ async function install(args) {
|
|
|
364
365
|
}
|
|
365
366
|
|
|
366
367
|
// Verificar dependencias con instalación automática
|
|
367
|
-
await checkAndInstallDependencies(sudoPassword);
|
|
368
|
+
await checkAndInstallDependencies(sudoPassword, skipAuth);
|
|
368
369
|
|
|
369
370
|
const templatesPath = getTemplatesPath();
|
|
370
371
|
const hooksPath = '.git/hooks';
|
|
@@ -411,15 +412,26 @@ async function install(args) {
|
|
|
411
412
|
success('.claude directory created');
|
|
412
413
|
}
|
|
413
414
|
|
|
414
|
-
// Copiar archivos de pautas a .claude
|
|
415
|
-
const
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
415
|
+
// Copiar archivos de pautas y prompts a .claude
|
|
416
|
+
const claudeFiles = [
|
|
417
|
+
'CLAUDE_PRE_COMMIT.md',
|
|
418
|
+
'CLAUDE_PRE_COMMIT_SONAR.md',
|
|
419
|
+
'CLAUDE_ANALYSIS_PROMPT.md',
|
|
420
|
+
'CLAUDE_ANALYSIS_PROMPT_SONAR.md',
|
|
421
|
+
'CLAUDE_RESOLUTION_PROMPT.md'
|
|
422
|
+
];
|
|
423
|
+
|
|
424
|
+
claudeFiles.forEach(file => {
|
|
425
|
+
const destPath = path.join(claudeDir, file);
|
|
426
|
+
const sourcePath = path.join(templatesPath, file);
|
|
427
|
+
|
|
428
|
+
// En modo force o si no existe, copiar el archivo
|
|
429
|
+
if (isForce || !fs.existsSync(destPath)) {
|
|
420
430
|
if (fs.existsSync(sourcePath)) {
|
|
421
431
|
fs.copyFileSync(sourcePath, destPath);
|
|
422
|
-
success(`${
|
|
432
|
+
success(`${file} instalado en .claude/`);
|
|
433
|
+
} else {
|
|
434
|
+
warning(`Archivo de template no encontrado: ${file}`);
|
|
423
435
|
}
|
|
424
436
|
}
|
|
425
437
|
});
|
|
@@ -438,7 +450,7 @@ async function install(args) {
|
|
|
438
450
|
}
|
|
439
451
|
|
|
440
452
|
// Verificar dependencias completas (como setup-wsl.sh)
|
|
441
|
-
async function checkAndInstallDependencies(sudoPassword = null) {
|
|
453
|
+
async function checkAndInstallDependencies(sudoPassword = null, skipAuth = false) {
|
|
442
454
|
info('Verificando dependencias del sistema...');
|
|
443
455
|
|
|
444
456
|
// Verificar Node.js
|
|
@@ -522,8 +534,12 @@ async function checkAndInstallDependencies(sudoPassword = null) {
|
|
|
522
534
|
// Verificar e instalar Claude CLI
|
|
523
535
|
await checkAndInstallClaude();
|
|
524
536
|
|
|
525
|
-
// Verificar autenticación de Claude
|
|
526
|
-
|
|
537
|
+
// Verificar autenticación de Claude (si no se salta)
|
|
538
|
+
if (!skipAuth) {
|
|
539
|
+
await checkClaudeAuth();
|
|
540
|
+
} else {
|
|
541
|
+
warning('Saltando verificación de autenticación de Claude (--skip-auth)');
|
|
542
|
+
}
|
|
527
543
|
|
|
528
544
|
// Limpiar contraseña de memoria
|
|
529
545
|
sudoPassword = null;
|
|
@@ -619,7 +635,8 @@ function updateGitignore() {
|
|
|
619
635
|
'# Claude Git Hooks',
|
|
620
636
|
'.claude/',
|
|
621
637
|
'.claude-analysis-mode',
|
|
622
|
-
'debug-claude-response.json'
|
|
638
|
+
'debug-claude-response.json',
|
|
639
|
+
'claude_resolution_prompt.md'
|
|
623
640
|
];
|
|
624
641
|
|
|
625
642
|
let gitignoreContent = '';
|
|
@@ -970,7 +987,9 @@ Claude Git Hooks - Análisis de código y mensajes automáticos con Claude CLI
|
|
|
970
987
|
Uso: claude-hooks <comando> [opciones]
|
|
971
988
|
|
|
972
989
|
Comandos:
|
|
973
|
-
install
|
|
990
|
+
install [opciones] Instala los hooks en el repositorio actual
|
|
991
|
+
--force Reinstala aunque ya existan
|
|
992
|
+
--skip-auth Salta la verificación de autenticación de Claude
|
|
974
993
|
update Actualiza a la última versión disponible
|
|
975
994
|
uninstall Desinstala los hooks del repositorio
|
|
976
995
|
enable [hook] Habilita hooks (todos o uno específico)
|
|
@@ -985,6 +1004,7 @@ Hooks disponibles:
|
|
|
985
1004
|
|
|
986
1005
|
Ejemplos:
|
|
987
1006
|
claude-hooks install # Instala todos los hooks
|
|
1007
|
+
claude-hooks install --skip-auth # Instala sin verificar autenticación
|
|
988
1008
|
claude-hooks update # Actualiza a la última versión
|
|
989
1009
|
claude-hooks set-mode sonar # Cambiar a modo SonarQube
|
|
990
1010
|
claude-hooks set-mode standard # Cambiar a modo estándar
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-git-hooks",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.1",
|
|
4
4
|
"description": "Git hooks con Claude CLI para análisis de código y generación automática de mensajes de commit",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -38,4 +38,4 @@
|
|
|
38
38
|
"CHANGELOG.md",
|
|
39
39
|
"LICENSE"
|
|
40
40
|
]
|
|
41
|
-
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
Eres un revisor de código senior con experiencia en proyectos Spring Boot empresariales.
|
|
2
|
+
|
|
3
|
+
Tu tarea es analizar los siguientes cambios de código y responder exclusivamente con un JSON válido, **sin ningún texto fuera del JSON**, sin introducciones ni explicaciones adicionales.
|
|
4
|
+
|
|
5
|
+
⚠️ La respuesta debe ser un objeto JSON con esta estructura exacta:
|
|
6
|
+
|
|
7
|
+
```json
|
|
8
|
+
{
|
|
9
|
+
"approved": true, // true si el commit puede aceptarse, false si debe bloquearse
|
|
10
|
+
"score": 1-10, // calificación de calidad (entero)
|
|
11
|
+
"blockingIssues": [ // SIEMPRE array de objetos, nunca strings
|
|
12
|
+
{
|
|
13
|
+
"description": "texto descriptivo del problema",
|
|
14
|
+
"file": "path/to/file.java",
|
|
15
|
+
"line": 123, // línea donde se detectó el problema
|
|
16
|
+
"method": "methodName", // método o clase afectada
|
|
17
|
+
"severity": "critical" // critical, high, medium, low
|
|
18
|
+
}
|
|
19
|
+
],
|
|
20
|
+
"recommendations": [ // sugerencias no bloqueantes (array de strings)
|
|
21
|
+
"mejora 1",
|
|
22
|
+
"mejora 2"
|
|
23
|
+
],
|
|
24
|
+
"details": {
|
|
25
|
+
"security": [ // comentarios específicos por área
|
|
26
|
+
"observación sobre seguridad"
|
|
27
|
+
],
|
|
28
|
+
"architecture": [ "..." ],
|
|
29
|
+
"performance": [ "..." ],
|
|
30
|
+
"maintainability": [ "..." ]
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
✅ Importante:
|
|
36
|
+
- blockingIssues SIEMPRE debe ser un array de objetos, NUNCA un array de strings
|
|
37
|
+
- Cada blockingIssue DEBE incluir: description, file, line, method, severity
|
|
38
|
+
- Usa listas vacías si no hay issues (ejemplo: `"blockingIssues": []`)
|
|
39
|
+
- No uses texto introductorio o explicaciones fuera del JSON
|
|
40
|
+
- No omitas claves aunque estén vacías
|
|
41
|
+
- Sé directo, claro y profesional en tus observaciones
|
|
42
|
+
- Los problemas críticos deben incluir contexto suficiente para que otra IA pueda resolverlos
|
|
43
|
+
|
|
44
|
+
A continuación se detallan las pautas y los cambios:
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
Eres un revisor de código senior con experiencia en proyectos Spring Boot empresariales y métricas SonarQube.
|
|
2
|
+
|
|
3
|
+
Tu tarea es analizar los siguientes cambios de código desde una perspectiva de calidad similar a SonarQube y responder exclusivamente con un JSON válido, **sin ningún texto fuera del JSON**, sin introducciones ni explicaciones adicionales.
|
|
4
|
+
|
|
5
|
+
⚠️ La respuesta debe ser un objeto JSON con esta estructura exacta de SonarQube:
|
|
6
|
+
|
|
7
|
+
```json
|
|
8
|
+
{
|
|
9
|
+
"QUALITY_GATE": "PASSED", // PASSED o FAILED
|
|
10
|
+
"approved": true, // compatibilidad con modo estándar
|
|
11
|
+
"score": 1-10, // calificación general
|
|
12
|
+
"metrics": {
|
|
13
|
+
"reliability": "A", // A, B, C, D, E
|
|
14
|
+
"security": "A", // A, B, C, D, E
|
|
15
|
+
"maintainability": "A", // A, B, C, D, E
|
|
16
|
+
"coverage": 85, // porcentaje de cobertura estimado
|
|
17
|
+
"duplications": 2, // porcentaje de duplicación estimado
|
|
18
|
+
"complexity": 15 // complejidad ciclomática estimada
|
|
19
|
+
},
|
|
20
|
+
"issues": {
|
|
21
|
+
"blocker": 0, // cantidad de issues bloqueantes
|
|
22
|
+
"critical": 0, // cantidad de issues críticos
|
|
23
|
+
"major": 0, // cantidad de issues mayores
|
|
24
|
+
"minor": 0, // cantidad de issues menores
|
|
25
|
+
"info": 0 // cantidad de issues informativos
|
|
26
|
+
},
|
|
27
|
+
"details": [ // detalle de cada issue encontrado con localización
|
|
28
|
+
{
|
|
29
|
+
"severity": "CRITICAL", // BLOCKER, CRITICAL, MAJOR, MINOR, INFO
|
|
30
|
+
"type": "BUG", // BUG, VULNERABILITY, CODE_SMELL
|
|
31
|
+
"file": "src/main/java/Example.java",
|
|
32
|
+
"line": 42,
|
|
33
|
+
"method": "processData", // método o clase afectada
|
|
34
|
+
"message": "Null pointer dereference possible",
|
|
35
|
+
"rule": "java:S2259" // regla de SonarQube (opcional)
|
|
36
|
+
}
|
|
37
|
+
],
|
|
38
|
+
"blockingIssues": [ // SIEMPRE array de objetos con issues BLOCKER y CRITICAL
|
|
39
|
+
{
|
|
40
|
+
"description": "texto descriptivo del problema",
|
|
41
|
+
"file": "path/to/file.java",
|
|
42
|
+
"line": 123,
|
|
43
|
+
"method": "methodName",
|
|
44
|
+
"severity": "critical" // solo "blocker" o "critical" aquí
|
|
45
|
+
}
|
|
46
|
+
],
|
|
47
|
+
"securityHotspots": 0 // cantidad de security hotspots
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
✅ Importante:
|
|
52
|
+
- blockingIssues SIEMPRE debe ser un array de objetos, NUNCA un array de strings
|
|
53
|
+
- blockingIssues debe contener TODOS los issues BLOCKER y CRITICAL del array details
|
|
54
|
+
- Cada blockingIssue DEBE incluir: description, file, line, method, severity
|
|
55
|
+
- El QUALITY_GATE debe ser FAILED si hay issues BLOCKER o CRITICAL
|
|
56
|
+
- Los ratings (A-E) deben reflejar la calidad real del código
|
|
57
|
+
- Para cada issue en details, SIEMPRE incluye file, line y method para localización precisa
|
|
58
|
+
- No uses texto fuera del JSON
|
|
59
|
+
- Sé preciso con las localizaciones para facilitar la resolución automatizada
|
|
60
|
+
|
|
61
|
+
A continuación se detallan las pautas y los cambios:
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# AI Resolution Assistant Prompt
|
|
2
|
+
|
|
3
|
+
You are an expert code reviewer tasked with resolving critical issues identified in a code review. Your goal is to provide precise, minimal, and efficient fixes.
|
|
4
|
+
|
|
5
|
+
## Context
|
|
6
|
+
Repository: {{REPO_NAME}}
|
|
7
|
+
Branch: {{BRANCH_NAME}}
|
|
8
|
+
Commit: {{COMMIT_SHA}}
|
|
9
|
+
Files analyzed: {{FILE_COUNT}}
|
|
10
|
+
Analysis mode: {{ANALYSIS_MODE}}
|
|
11
|
+
|
|
12
|
+
## Critical Issues to Resolve
|
|
13
|
+
|
|
14
|
+
{{BLOCKING_ISSUES}}
|
|
15
|
+
|
|
16
|
+
## Affected Files Content
|
|
17
|
+
|
|
18
|
+
{{FILE_CONTENTS}}
|
|
19
|
+
|
|
20
|
+
## Instructions
|
|
21
|
+
|
|
22
|
+
1. For each critical issue:
|
|
23
|
+
- Navigate to the exact file and line number specified
|
|
24
|
+
- Understand the context and the problem
|
|
25
|
+
- Apply the minimal fix required
|
|
26
|
+
- Ensure the fix doesn't introduce new issues
|
|
27
|
+
|
|
28
|
+
2. Fix requirements:
|
|
29
|
+
- Make the smallest possible change to resolve the issue
|
|
30
|
+
- Maintain existing code style and conventions
|
|
31
|
+
- Don't refactor unrelated code
|
|
32
|
+
- Preserve all existing functionality
|
|
33
|
+
|
|
34
|
+
3. Output format:
|
|
35
|
+
- Provide exact code changes using diff format
|
|
36
|
+
- Include file path, line numbers, and context
|
|
37
|
+
- Explain each fix briefly (one line max)
|
|
38
|
+
|
|
39
|
+
## Fix Priority
|
|
40
|
+
1. Security vulnerabilities (highest)
|
|
41
|
+
2. Null pointer / runtime errors
|
|
42
|
+
3. Logic errors
|
|
43
|
+
4. Performance issues
|
|
44
|
+
5. Code quality issues (lowest)
|
|
45
|
+
|
|
46
|
+
Begin fixing the issues in order of severity.
|
package/templates/pre-commit
CHANGED
|
@@ -56,6 +56,99 @@ if [ -n "$CHECK_VERSION_SCRIPT" ]; then
|
|
|
56
56
|
check_version
|
|
57
57
|
fi
|
|
58
58
|
|
|
59
|
+
# Función para generar prompt de resolución AI-friendly
|
|
60
|
+
generate_resolution_prompt() {
|
|
61
|
+
local RESOLUTION_FILE="./claude_resolution_prompt.md"
|
|
62
|
+
local RESOLUTION_TEMPLATE=".claude/CLAUDE_RESOLUTION_PROMPT.md"
|
|
63
|
+
|
|
64
|
+
if [ ! -f "$RESOLUTION_TEMPLATE" ]; then
|
|
65
|
+
warning "No se encontró template de resolución: $RESOLUTION_TEMPLATE"
|
|
66
|
+
return
|
|
67
|
+
fi
|
|
68
|
+
|
|
69
|
+
# Obtener información del contexto
|
|
70
|
+
local REPO_NAME=$(basename $(git rev-parse --show-toplevel))
|
|
71
|
+
local BRANCH_NAME=$(git rev-parse --abbrev-ref HEAD)
|
|
72
|
+
local COMMIT_SHA="pending"
|
|
73
|
+
local FILE_COUNT=$(echo "$JAVA_FILES" | wc -l)
|
|
74
|
+
|
|
75
|
+
# Formatear los blocking issues para el prompt de resolución
|
|
76
|
+
local ISSUES_FORMATTED=""
|
|
77
|
+
local issue_num=1
|
|
78
|
+
|
|
79
|
+
# Usar un archivo temporal para acumular los issues
|
|
80
|
+
local TEMP_ISSUES=$(mktemp)
|
|
81
|
+
|
|
82
|
+
# Parsear cada blocking issue como objeto JSON
|
|
83
|
+
echo "$JSON_RESPONSE" | jq -c '.blockingIssues[]?' 2>/dev/null | while IFS= read -r issue; do
|
|
84
|
+
if [ -n "$issue" ]; then
|
|
85
|
+
local desc=$(echo "$issue" | jq -r '.description')
|
|
86
|
+
local file=$(echo "$issue" | jq -r '.file')
|
|
87
|
+
local line=$(echo "$issue" | jq -r '.line')
|
|
88
|
+
local method=$(echo "$issue" | jq -r '.method')
|
|
89
|
+
local severity=$(echo "$issue" | jq -r '.severity')
|
|
90
|
+
|
|
91
|
+
echo "### Issue #${issue_num} [${severity^^}]" >> "$TEMP_ISSUES"
|
|
92
|
+
echo "**Description:** ${desc}" >> "$TEMP_ISSUES"
|
|
93
|
+
echo "**Location:** ${file}:${line}" >> "$TEMP_ISSUES"
|
|
94
|
+
echo "**Method/Class:** ${method}" >> "$TEMP_ISSUES"
|
|
95
|
+
echo "" >> "$TEMP_ISSUES"
|
|
96
|
+
issue_num=$((issue_num + 1))
|
|
97
|
+
fi
|
|
98
|
+
done
|
|
99
|
+
|
|
100
|
+
# Leer el contenido acumulado
|
|
101
|
+
ISSUES_FORMATTED=$(cat "$TEMP_ISSUES")
|
|
102
|
+
rm -f "$TEMP_ISSUES"
|
|
103
|
+
|
|
104
|
+
# Generar el prompt desde el template
|
|
105
|
+
cp "$RESOLUTION_TEMPLATE" "$RESOLUTION_FILE"
|
|
106
|
+
|
|
107
|
+
# Reemplazar placeholders - usar comillas dobles y escapar caracteres especiales
|
|
108
|
+
sed -i "s|{{REPO_NAME}}|${REPO_NAME}|g" "$RESOLUTION_FILE"
|
|
109
|
+
sed -i "s|{{BRANCH_NAME}}|${BRANCH_NAME}|g" "$RESOLUTION_FILE"
|
|
110
|
+
sed -i "s|{{COMMIT_SHA}}|${COMMIT_SHA}|g" "$RESOLUTION_FILE"
|
|
111
|
+
sed -i "s|{{FILE_COUNT}}|${FILE_COUNT}|g" "$RESOLUTION_FILE"
|
|
112
|
+
sed -i "s|{{ANALYSIS_MODE}}|${ANALYSIS_MODE:-standard}|g" "$RESOLUTION_FILE"
|
|
113
|
+
|
|
114
|
+
# Crear archivo temporal para issues formateados
|
|
115
|
+
local TEMP_ISSUES_FILE=$(mktemp)
|
|
116
|
+
echo "$ISSUES_FORMATTED" > "$TEMP_ISSUES_FILE"
|
|
117
|
+
|
|
118
|
+
# Reemplazar {{BLOCKING_ISSUES}} con el contenido
|
|
119
|
+
if [ -n "$ISSUES_FORMATTED" ]; then
|
|
120
|
+
sed -i "/{{BLOCKING_ISSUES}}/r $TEMP_ISSUES_FILE" "$RESOLUTION_FILE"
|
|
121
|
+
fi
|
|
122
|
+
sed -i "s|{{BLOCKING_ISSUES}}||g" "$RESOLUTION_FILE"
|
|
123
|
+
rm -f "$TEMP_ISSUES_FILE"
|
|
124
|
+
|
|
125
|
+
# Agregar contenido de archivos afectados
|
|
126
|
+
local TEMP_FILES=$(mktemp)
|
|
127
|
+
echo "$JSON_RESPONSE" | jq -r '.blockingIssues[].file' 2>/dev/null | sort -u | while IFS= read -r file; do
|
|
128
|
+
if [ -f "$file" ]; then
|
|
129
|
+
echo "### File: $file" >> "$TEMP_FILES"
|
|
130
|
+
echo "" >> "$TEMP_FILES"
|
|
131
|
+
echo '```' >> "$TEMP_FILES"
|
|
132
|
+
cat "$file" >> "$TEMP_FILES"
|
|
133
|
+
echo '```' >> "$TEMP_FILES"
|
|
134
|
+
echo "" >> "$TEMP_FILES"
|
|
135
|
+
fi
|
|
136
|
+
done
|
|
137
|
+
|
|
138
|
+
# Reemplazar {{FILE_CONTENTS}} con el contenido
|
|
139
|
+
if [ -s "$TEMP_FILES" ]; then
|
|
140
|
+
sed -i "/{{FILE_CONTENTS}}/r $TEMP_FILES" "$RESOLUTION_FILE"
|
|
141
|
+
fi
|
|
142
|
+
sed -i "s|{{FILE_CONTENTS}}||g" "$RESOLUTION_FILE"
|
|
143
|
+
rm -f "$TEMP_FILES"
|
|
144
|
+
|
|
145
|
+
echo
|
|
146
|
+
echo -e "${YELLOW}=== PROMPT DE RESOLUCIÓN AI GENERADO ===${NC}"
|
|
147
|
+
echo -e "${GREEN}Se ha generado un prompt AI-friendly en: ${BLUE}$RESOLUTION_FILE${NC}"
|
|
148
|
+
echo -e "${YELLOW}Copia este archivo a una nueva instancia de Claude para resolver los problemas automáticamente.${NC}"
|
|
149
|
+
echo
|
|
150
|
+
}
|
|
151
|
+
|
|
59
152
|
# Detectar qué archivo de pautas usar
|
|
60
153
|
# Prioridad: variable de entorno > archivo > pregunta interactiva
|
|
61
154
|
if [ -n "$CLAUDE_ANALYSIS_MODE" ]; then
|
|
@@ -92,9 +185,11 @@ if [ "$ANALYSIS_MODE" != "standard" ] && [ "$ANALYSIS_MODE" != "sonar" ]; then
|
|
|
92
185
|
if [ "$REPLY" = "2" ]; then
|
|
93
186
|
ANALYSIS_MODE="sonar"
|
|
94
187
|
GUIDELINES_FILE=".claude/CLAUDE_PRE_COMMIT_SONAR.md"
|
|
188
|
+
PROMPT_TEMPLATE=".claude/CLAUDE_ANALYSIS_PROMPT_SONAR.md"
|
|
95
189
|
else
|
|
96
190
|
ANALYSIS_MODE="standard"
|
|
97
191
|
GUIDELINES_FILE=".claude/CLAUDE_PRE_COMMIT.md"
|
|
192
|
+
PROMPT_TEMPLATE=".claude/CLAUDE_ANALYSIS_PROMPT.md"
|
|
98
193
|
fi
|
|
99
194
|
|
|
100
195
|
# Guardar preferencia para futuros commits
|
|
@@ -106,12 +201,23 @@ else
|
|
|
106
201
|
# Usar modo guardado
|
|
107
202
|
if [ "$ANALYSIS_MODE" = "sonar" ]; then
|
|
108
203
|
GUIDELINES_FILE=".claude/CLAUDE_PRE_COMMIT_SONAR.md"
|
|
204
|
+
PROMPT_TEMPLATE=".claude/CLAUDE_ANALYSIS_PROMPT_SONAR.md"
|
|
109
205
|
log "Usando modo de análisis: SonarQube"
|
|
110
206
|
else
|
|
111
207
|
GUIDELINES_FILE=".claude/CLAUDE_PRE_COMMIT.md"
|
|
208
|
+
PROMPT_TEMPLATE=".claude/CLAUDE_ANALYSIS_PROMPT.md"
|
|
112
209
|
log "Usando modo de análisis: Estándar"
|
|
113
210
|
fi
|
|
114
211
|
fi
|
|
212
|
+
|
|
213
|
+
# Verificar que el template de prompt existe
|
|
214
|
+
if [ ! -f "$PROMPT_TEMPLATE" ]; then
|
|
215
|
+
error "No se encontró el template de prompt: $PROMPT_TEMPLATE"
|
|
216
|
+
error "Los archivos de configuración de Claude parecen estar incompletos."
|
|
217
|
+
error "Por favor, reinstala claude-git-hooks ejecutando:"
|
|
218
|
+
error " claude-hooks install --force"
|
|
219
|
+
exit 1
|
|
220
|
+
fi
|
|
115
221
|
# Función para limpiar archivos temporales
|
|
116
222
|
cleanup() {
|
|
117
223
|
rm -rf "$TEMP_DIR"
|
|
@@ -140,9 +246,10 @@ fi
|
|
|
140
246
|
|
|
141
247
|
# Verificar si existe el archivo de pautas
|
|
142
248
|
if [ ! -f "$GUIDELINES_FILE" ]; then
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
249
|
+
error "No se encontró el archivo de pautas: $GUIDELINES_FILE"
|
|
250
|
+
error "Por favor, reinstala claude-git-hooks ejecutando:"
|
|
251
|
+
error " claude-hooks install --force"
|
|
252
|
+
exit 1
|
|
146
253
|
fi
|
|
147
254
|
|
|
148
255
|
log "Archivos Java/config a revisar: $(echo "$JAVA_FILES" | wc -l)"
|
|
@@ -150,42 +257,8 @@ log "Archivos Java/config a revisar: $(echo "$JAVA_FILES" | wc -l)"
|
|
|
150
257
|
# Construir el prompt para análisis de código
|
|
151
258
|
PROMPT_FILE="$TEMP_DIR/code_review_prompt.txt"
|
|
152
259
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
Tu tarea es analizar los siguientes cambios de código y responder exclusivamente con un JSON válido, **sin ningún texto fuera del JSON**, sin introducciones ni explicaciones adicionales.
|
|
157
|
-
|
|
158
|
-
⚠️ La respuesta debe ser un objeto JSON con esta estructura exacta:
|
|
159
|
-
|
|
160
|
-
{
|
|
161
|
-
"approved": true, // true si el commit puede aceptarse, false si debe bloquearse
|
|
162
|
-
"score": 1-10, // calificación de calidad (entero)
|
|
163
|
-
"blockingIssues": [ // lista de errores críticos (vacía si no hay)
|
|
164
|
-
"texto descriptivo 1",
|
|
165
|
-
"texto descriptivo 2"
|
|
166
|
-
],
|
|
167
|
-
"recommendations": [ // sugerencias no bloqueantes
|
|
168
|
-
"mejora 1",
|
|
169
|
-
"mejora 2"
|
|
170
|
-
],
|
|
171
|
-
"details": {
|
|
172
|
-
"security": [ // comentarios específicos por área
|
|
173
|
-
"observación sobre seguridad"
|
|
174
|
-
],
|
|
175
|
-
"architecture": [ "..." ],
|
|
176
|
-
"performance": [ "..." ],
|
|
177
|
-
"maintainability": [ "..." ]
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
✅ Importante:
|
|
182
|
-
- Usa listas aunque estén vacías (por ejemplo `"blockingIssues": []`)
|
|
183
|
-
- No uses texto introductorio o explicaciones fuera del JSON
|
|
184
|
-
- No omitas claves aunque estén vacías
|
|
185
|
-
- Sé directo, claro y profesional en tus observaciones
|
|
186
|
-
|
|
187
|
-
A continuación se detallan las pautas y los cambios:
|
|
188
|
-
EOF
|
|
260
|
+
# Copiar el template de prompt
|
|
261
|
+
cat "$PROMPT_TEMPLATE" > "$PROMPT_FILE"
|
|
189
262
|
|
|
190
263
|
# Agregar las pautas
|
|
191
264
|
echo "=== PAUTAS DE EVALUACIÓN ===" >> "$PROMPT_FILE"
|
|
@@ -257,7 +330,14 @@ if $CLAUDE_CLI < "$PROMPT_FILE" > "$RESPONSE_FILE" 2>&1; then
|
|
|
257
330
|
APPROVED=$(echo "$JSON_RESPONSE" | jq -r '.approved // false')
|
|
258
331
|
SCORE=$(echo "$JSON_RESPONSE" | jq -r '.score // 0')
|
|
259
332
|
RECOMMENDATIONS=$(echo "$JSON_RESPONSE" | jq -r '.recommendations[]?' 2>/dev/null | sed '/^$/d')
|
|
260
|
-
|
|
333
|
+
|
|
334
|
+
# Parsear blockingIssues como objetos y extraer las descripciones
|
|
335
|
+
BLOCKING_ISSUES=""
|
|
336
|
+
BLOCKING_COUNT=$(echo "$JSON_RESPONSE" | jq '.blockingIssues | length' 2>/dev/null || echo "0")
|
|
337
|
+
|
|
338
|
+
if [ "$BLOCKING_COUNT" -gt 0 ]; then
|
|
339
|
+
BLOCKING_ISSUES=$(echo "$JSON_RESPONSE" | jq -r '.blockingIssues[].description' 2>/dev/null | sed '/^$/d')
|
|
340
|
+
fi
|
|
261
341
|
|
|
262
342
|
# Verificar si estamos en modo SonarQube
|
|
263
343
|
QUALITY_GATE=$(echo "$JSON_RESPONSE" | jq -r '.QUALITY_GATE // ""' 2>/dev/null)
|
|
@@ -356,6 +436,9 @@ if $CLAUDE_CLI < "$PROMPT_FILE" > "$RESPONSE_FILE" 2>&1; then
|
|
|
356
436
|
echo
|
|
357
437
|
echo "=== PROBLEMAS CRÍTICOS ==="
|
|
358
438
|
echo "$BLOCKING_ISSUES" | sed 's/^/- /'
|
|
439
|
+
|
|
440
|
+
# Generar prompt de resolución AI-friendly
|
|
441
|
+
generate_resolution_prompt
|
|
359
442
|
fi
|
|
360
443
|
exit 1
|
|
361
444
|
fi
|