claude-git-hooks 2.0.0 → 2.1.0
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 +34 -0
- package/README.md +14 -13
- package/bin/claude-hooks +24 -38
- package/lib/hooks/pre-commit.js +1 -1
- package/lib/utils/file-operations.js +22 -9
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,40 @@ 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
|
+
## [2.1.0] - 2025-11-04
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- 🔄 Renombrado marcador de exclusión de línea única: `// SKIP-ANALYSIS` → `// SKIP_ANALYSIS_LINE` para consistencia de nomenclatura
|
|
13
|
+
- 🐛 Corregido bug crítico en orden de detección de patrones que impedía funcionamiento de `SKIP_ANALYSIS_BLOCK`
|
|
14
|
+
|
|
15
|
+
### Known Issues
|
|
16
|
+
|
|
17
|
+
- ⚠️ **SKIP_ANALYSIS marcado como EXPERIMENTAL/BROKEN**: Los marcadores de exclusión no funcionan correctamente porque el análisis se realiza sobre git diff en lugar del archivo completo. Marcadores agregados en commits anteriores no son detectados en cambios subsecuentes.
|
|
18
|
+
|
|
19
|
+
### Migration Guide
|
|
20
|
+
|
|
21
|
+
Si utilizabas `// SKIP-ANALYSIS` en tu código, reemplázalo por `// SKIP_ANALYSIS_LINE`:
|
|
22
|
+
|
|
23
|
+
```java
|
|
24
|
+
// Antes (deprecated):
|
|
25
|
+
// SKIP-ANALYSIS
|
|
26
|
+
private String legacyCode;
|
|
27
|
+
|
|
28
|
+
// Ahora:
|
|
29
|
+
// SKIP_ANALYSIS_LINE
|
|
30
|
+
private String legacyCode;
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
El marcador de bloque `// SKIP_ANALYSIS_BLOCK` permanece sin cambios.
|
|
34
|
+
|
|
35
|
+
## [2.0.1] - 2025-11-04
|
|
36
|
+
|
|
37
|
+
### Fixed
|
|
38
|
+
|
|
39
|
+
- 🔧 Compatibilidad completa en Windows: corregidos line endings CRLF, validación WSL, y comparación de versiones sin dependencia bash
|
|
40
|
+
- 🔧 Operaciones de rutas utilizan módulo `path` nativo para mejor portabilidad multiplataforma
|
|
41
|
+
|
|
8
42
|
## [2.0.0] - 2025-10-30
|
|
9
43
|
|
|
10
44
|
### 🚀 BREAKING CHANGE: Migration from Bash to Node.js Hooks
|
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
- 🔍 **Análisis de código pre-commit**: Detecta issues críticos antes de que lleguen al repo
|
|
17
17
|
- 💬 **Mensajes de commit automáticos**: Escribe "auto" y Claude genera el mensaje
|
|
18
18
|
- 📋 **Generación de PRs**: Título, descripción y tests sugeridos con un solo comando
|
|
19
|
-
-
|
|
19
|
+
- ⚠️ **Skip inteligente** (EXPERIMENTAL/BROKEN): Exclusión de código con comentarios SKIP_ANALYSIS - no funciona correctamente con git diff
|
|
20
20
|
- 🕵️♂️ **Paralelización**: Análisis asincrónico de archivos con sub agentes
|
|
21
21
|
- 🔄 **Auto-actualización**: Se mantiene actualizado automáticamente
|
|
22
22
|
- 🌍 **Cross-platform**: Windows, WSL, macOS, Linux sin configuración especial
|
|
@@ -85,10 +85,13 @@ git commit --no-verify -m "hotfix: corrección urgente"
|
|
|
85
85
|
git commit --amend
|
|
86
86
|
```
|
|
87
87
|
|
|
88
|
-
###
|
|
88
|
+
### ⚠️ Exclusión de Código del Análisis (EXPERIMENTAL/BROKEN)
|
|
89
89
|
|
|
90
90
|
```java
|
|
91
|
-
//
|
|
91
|
+
// NOTA: Este feature NO funciona correctamente
|
|
92
|
+
// Los marcadores no son detectados si fueron agregados en commits anteriores
|
|
93
|
+
|
|
94
|
+
// SKIP_ANALYSIS_LINE
|
|
92
95
|
private String legacyCode = "no analizar siguiente línea";
|
|
93
96
|
|
|
94
97
|
// SKIP_ANALYSIS_BLOCK
|
|
@@ -347,21 +350,19 @@ Si no existe un `.gitignore`, se creará uno nuevo. Si ya existe, las entradas s
|
|
|
347
350
|
- **Modo debug**: `DEBUG=1 git commit` guarda respuestas en `debug-claude-response.json`
|
|
348
351
|
- **Análisis de PR**: Nuevo comando `analyze-diff` para generar información de Pull Requests
|
|
349
352
|
- **Validación de dependencias**: Verifica que Claude CLI esté autenticado antes de ejecutar
|
|
350
|
-
-
|
|
353
|
+
- **⚠️ Exclusión de código del análisis (EXPERIMENTAL/BROKEN)**: Los marcadores `// SKIP_ANALYSIS_LINE` y `// SKIP_ANALYSIS_BLOCK` no funcionan correctamente. El hook analiza git diff en lugar del archivo completo, por lo que marcadores agregados en commits anteriores no son detectados en cambios subsecuentes.
|
|
351
354
|
|
|
352
355
|
```java
|
|
353
|
-
//
|
|
354
|
-
//
|
|
355
|
-
@Autowired private LegacyService legacyService;
|
|
356
|
+
// NOTA: Este feature actualmente NO funciona de forma confiable
|
|
357
|
+
// SKIP_ANALYSIS_LINE
|
|
358
|
+
@Autowired private LegacyService legacyService;
|
|
356
359
|
|
|
357
|
-
//
|
|
358
|
-
// SKIP-ANALYSIS_BLOCK
|
|
360
|
+
// SKIP_ANALYSIS_BLOCK
|
|
359
361
|
@Deprecated
|
|
360
362
|
public void methodWithKnownIssues() {
|
|
361
|
-
|
|
362
|
-
System.out.println("Debug temporal");
|
|
363
|
+
System.out.println("Legacy code");
|
|
363
364
|
}
|
|
364
|
-
//
|
|
365
|
+
// SKIP_ANALYSIS_BLOCK
|
|
365
366
|
```
|
|
366
367
|
|
|
367
368
|
### Desactivar/Activar hooks
|
|
@@ -437,7 +438,7 @@ claude-git-hooks/
|
|
|
437
438
|
│ └── utils/
|
|
438
439
|
│ ├── logger.js # Sistema de logging centralizado
|
|
439
440
|
│ ├── git-operations.js # Operaciones git abstractas
|
|
440
|
-
│ ├── file-operations.js # I/O con filtro
|
|
441
|
+
│ ├── file-operations.js # I/O con filtro SKIP_ANALYSIS_LINE
|
|
441
442
|
│ ├── claude-client.js # Cliente Claude CLI
|
|
442
443
|
│ ├── prompt-builder.js # Constructor de prompts
|
|
443
444
|
│ └── resolution-prompt.js # Generador de resolution prompts
|
package/bin/claude-hooks
CHANGED
|
@@ -429,11 +429,10 @@ async function install(args) {
|
|
|
429
429
|
console.log(' git commit -m "auto" # Generate message automatically');
|
|
430
430
|
console.log(' git commit -m "message" # Analyze code before commit');
|
|
431
431
|
console.log(' git commit --no-verify # Skip analysis completely');
|
|
432
|
-
console.log('\
|
|
433
|
-
console.log(' //
|
|
434
|
-
console.log(' // SKIP_ANALYSIS_BLOCK
|
|
435
|
-
console.log('
|
|
436
|
-
console.log(' // SKIP_ANALYSIS_BLOCK');
|
|
432
|
+
console.log('\n⚠️ Exclude code from analysis (EXPERIMENTAL/BROKEN):');
|
|
433
|
+
console.log(' // SKIP_ANALYSIS_LINE # Does NOT work reliably');
|
|
434
|
+
console.log(' // SKIP_ANALYSIS_BLOCK # Does NOT work reliably');
|
|
435
|
+
console.log(' // Reason: Analyzes git diff, not full file');
|
|
437
436
|
console.log('\nNEW: Parallel analysis for faster multi-file commits:');
|
|
438
437
|
console.log(' export CLAUDE_USE_SUBAGENTS=true # Enable subagents');
|
|
439
438
|
console.log(' export CLAUDE_SUBAGENT_MODEL=haiku # haiku/sonnet/opus');
|
|
@@ -1064,36 +1063,24 @@ function setMode(mode) {
|
|
|
1064
1063
|
}
|
|
1065
1064
|
}
|
|
1066
1065
|
|
|
1067
|
-
//
|
|
1066
|
+
// Cross-platform version comparison (semver)
|
|
1067
|
+
// Why: Pure JavaScript, no bash dependency
|
|
1068
|
+
// Returns: 0 if equal, 1 if v1 > v2, -1 if v1 < v2
|
|
1068
1069
|
function compareVersions(v1, v2) {
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
if (v1 === v2) return 0;
|
|
1081
|
-
const sorted = [v1, v2].sort((a, b) => {
|
|
1082
|
-
const aParts = a.split('.').map(Number);
|
|
1083
|
-
const bParts = b.split('.').map(Number);
|
|
1084
|
-
for (let i = 0; i < Math.max(aParts.length, bParts.length); i++) {
|
|
1085
|
-
const aPart = aParts[i] || 0;
|
|
1086
|
-
const bPart = bParts[i] || 0;
|
|
1087
|
-
if (aPart !== bPart) return aPart - bPart;
|
|
1088
|
-
}
|
|
1089
|
-
return 0;
|
|
1090
|
-
});
|
|
1091
|
-
return v1 === sorted[1] ? 1 : -1;
|
|
1092
|
-
} catch (e) {
|
|
1093
|
-
// Si falla todo, usar comparación simple
|
|
1094
|
-
if (v1 === v2) return 0;
|
|
1095
|
-
return v1 > v2 ? 1 : -1;
|
|
1070
|
+
if (v1 === v2) return 0;
|
|
1071
|
+
|
|
1072
|
+
const v1Parts = v1.split('.').map(Number);
|
|
1073
|
+
const v2Parts = v2.split('.').map(Number);
|
|
1074
|
+
|
|
1075
|
+
for (let i = 0; i < Math.max(v1Parts.length, v2Parts.length); i++) {
|
|
1076
|
+
const v1Part = v1Parts[i] || 0;
|
|
1077
|
+
const v2Part = v2Parts[i] || 0;
|
|
1078
|
+
|
|
1079
|
+
if (v1Part > v2Part) return 1;
|
|
1080
|
+
if (v1Part < v2Part) return -1;
|
|
1096
1081
|
}
|
|
1082
|
+
|
|
1083
|
+
return 0;
|
|
1097
1084
|
}
|
|
1098
1085
|
|
|
1099
1086
|
// Update command - update to the latest version
|
|
@@ -1189,11 +1176,10 @@ Analyze-diff use case:
|
|
|
1189
1176
|
→ PR Description: "## Summary\n- Added JWT authentication..."
|
|
1190
1177
|
→ Suggested branch: "feature/user-authentication"
|
|
1191
1178
|
|
|
1192
|
-
Exclude code from analysis:
|
|
1193
|
-
//
|
|
1194
|
-
// SKIP_ANALYSIS_BLOCK
|
|
1195
|
-
|
|
1196
|
-
// SKIP_ANALYSIS_BLOCK
|
|
1179
|
+
⚠️ Exclude code from analysis (EXPERIMENTAL/BROKEN):
|
|
1180
|
+
// SKIP_ANALYSIS_LINE # Does NOT work reliably
|
|
1181
|
+
// SKIP_ANALYSIS_BLOCK # Does NOT work reliably
|
|
1182
|
+
Reason: Analyzes git diff, not full file
|
|
1197
1183
|
|
|
1198
1184
|
Performance optimization (NEW in v1.5.5):
|
|
1199
1185
|
export CLAUDE_USE_SUBAGENTS=true # Enable parallel analysis for 3+ files
|
package/lib/hooks/pre-commit.js
CHANGED
|
@@ -121,11 +121,21 @@ const readFile = async (filePath, { maxSize = 100000, encoding = 'utf8' } = {})
|
|
|
121
121
|
};
|
|
122
122
|
|
|
123
123
|
/**
|
|
124
|
-
* Filters
|
|
124
|
+
* Filters SKIP_ANALYSIS patterns from code content
|
|
125
125
|
* Why: Allows developers to exclude specific code from analysis
|
|
126
126
|
*
|
|
127
|
+
* ⚠️ KNOWN ISSUE (EXPERIMENTAL/BROKEN):
|
|
128
|
+
* This feature does NOT work reliably. The pre-commit hook analyzes git diff
|
|
129
|
+
* instead of full file content. Markers added in previous commits are NOT
|
|
130
|
+
* present in subsequent diffs, so they are not detected.
|
|
131
|
+
*
|
|
132
|
+
* Example of failure:
|
|
133
|
+
* - Commit 1: Add // SKIP_ANALYSIS_BLOCK markers
|
|
134
|
+
* - Commit 2: Modify line inside block
|
|
135
|
+
* - Result: Diff only shows modified line, NOT the markers → filter fails
|
|
136
|
+
*
|
|
127
137
|
* Supports two patterns:
|
|
128
|
-
* 1. Single line: //
|
|
138
|
+
* 1. Single line: // SKIP_ANALYSIS_LINE (excludes next line)
|
|
129
139
|
* 2. Block: // SKIP_ANALYSIS_BLOCK ... // SKIP_ANALYSIS_BLOCK (excludes block)
|
|
130
140
|
*
|
|
131
141
|
* @param {string} content - File content to filter
|
|
@@ -134,7 +144,7 @@ const readFile = async (filePath, { maxSize = 100000, encoding = 'utf8' } = {})
|
|
|
134
144
|
const filterSkipAnalysis = (content) => {
|
|
135
145
|
logger.debug(
|
|
136
146
|
'file-operations - filterSkipAnalysis',
|
|
137
|
-
'Filtering
|
|
147
|
+
'Filtering SKIP_ANALYSIS patterns',
|
|
138
148
|
{ originalLength: content.length }
|
|
139
149
|
);
|
|
140
150
|
|
|
@@ -145,11 +155,8 @@ const filterSkipAnalysis = (content) => {
|
|
|
145
155
|
// Why: Use map instead of filter to preserve line numbers for error reporting
|
|
146
156
|
// Empty lines maintain original line number mapping
|
|
147
157
|
const filteredLines = lines.map((line) => {
|
|
148
|
-
//
|
|
149
|
-
|
|
150
|
-
skipNext = true;
|
|
151
|
-
return ''; // Preserve line number
|
|
152
|
-
}
|
|
158
|
+
// IMPORTANT: Check specific pattern first (SKIP_ANALYSIS_BLOCK)
|
|
159
|
+
// before general pattern (SKIP_ANALYSIS_LINE) to avoid substring match issues
|
|
153
160
|
|
|
154
161
|
// Detect SKIP_ANALYSIS_BLOCK (toggle block state)
|
|
155
162
|
if (line.includes('// SKIP_ANALYSIS_BLOCK')) {
|
|
@@ -157,12 +164,18 @@ const filterSkipAnalysis = (content) => {
|
|
|
157
164
|
return ''; // Preserve line number
|
|
158
165
|
}
|
|
159
166
|
|
|
167
|
+
// Detect single-line SKIP_ANALYSIS_LINE (must check AFTER block check)
|
|
168
|
+
if (line.includes('// SKIP_ANALYSIS_LINE')) {
|
|
169
|
+
skipNext = true;
|
|
170
|
+
return ''; // Preserve line number
|
|
171
|
+
}
|
|
172
|
+
|
|
160
173
|
// Skip lines inside block
|
|
161
174
|
if (inSkipBlock) {
|
|
162
175
|
return '';
|
|
163
176
|
}
|
|
164
177
|
|
|
165
|
-
// Skip next line after single
|
|
178
|
+
// Skip next line after single SKIP_ANALYSIS_LINE
|
|
166
179
|
if (skipNext) {
|
|
167
180
|
skipNext = false;
|
|
168
181
|
return '';
|