claude-git-hooks 2.19.0 → 2.20.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 +28 -0
- package/CLAUDE.md +78 -34
- package/README.md +52 -18
- package/lib/cli-metadata.js +5 -0
- package/lib/commands/diff-batch-info.js +105 -0
- package/lib/commands/install.js +0 -10
- package/lib/config.js +6 -27
- package/lib/hooks/pre-commit.js +43 -17
- package/lib/hooks/prepare-commit-msg.js +3 -24
- package/lib/utils/analysis-engine.js +62 -46
- package/lib/utils/claude-client.js +14 -66
- package/lib/utils/diff-analysis-orchestrator.js +332 -0
- package/lib/utils/judge.js +195 -0
- package/lib/utils/package-info.js +0 -11
- package/lib/utils/prompt-builder.js +15 -21
- package/lib/utils/resolution-prompt.js +1 -8
- package/lib/utils/telemetry.js +46 -10
- package/package.json +1 -1
- package/templates/CLAUDE_RESOLUTION_PROMPT.md +17 -9
- package/templates/DIFF_ANALYSIS_ORCHESTRATION_PROMPT.md +70 -0
- package/templates/config.advanced.example.json +15 -31
- package/templates/config.example.json +0 -11
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,34 @@ 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.20.0] - 2026-03-09
|
|
9
|
+
|
|
10
|
+
### ✨ Added
|
|
11
|
+
- Intelligent batch orchestration for commits with 3+ files using Opus to semantically group files, assign per-batch models, and inject shared commit context
|
|
12
|
+
- Auto-fix judge that evaluates all issues at any severity level, auto-applies search/replace fixes, and dismisses false positives - any unresolved issue blocks the commit (#85)
|
|
13
|
+
- New `batch-info` command to display orchestration configuration and per-model average analysis speed from telemetry
|
|
14
|
+
- Per-call model override capability in `analyzeCode()` for different Claude models per analysis batch
|
|
15
|
+
- New `diff-analysis-orchestrator.js` module for semantic batch grouping via Opus
|
|
16
|
+
- New `judge.js` module for LLM verdict and search/replace auto-fixes
|
|
17
|
+
- Cross-file dependency detection for JavaScript, TypeScript, Java, and Python files
|
|
18
|
+
- DIFF_ANALYSIS_ORCHESTRATION_PROMPT.md template for Opus batch grouping
|
|
19
|
+
|
|
20
|
+
### 🔧 Changed
|
|
21
|
+
- Analysis routing now uses three-tier strategy: 1-2 files use sequential single call, 3+ files trigger intelligent orchestration
|
|
22
|
+
- Judge now runs on all issues regardless of severity (previously only CRITICAL/BLOCKER blocked commits)
|
|
23
|
+
- Resolution prompt file is only generated if issues remain after judge evaluation
|
|
24
|
+
- Updated documentation to clarify that judge blocks commits when any issue remains unresolved
|
|
25
|
+
- Orchestrator threshold set to 3 files as internal constant in `analysis-engine.js`
|
|
26
|
+
- Each batch prompt now includes commit overview, dependency graph, and batch rationale for better cross-file reasoning
|
|
27
|
+
- Judge failures (timeout, JSON parse error, module load) now warn user and block commit
|
|
28
|
+
- Configurable judge model via `config.judge.model` (default: opus)
|
|
29
|
+
- Judge can be disabled via `config.judge.enabled: false` to fall back to original quality gate
|
|
30
|
+
|
|
31
|
+
### 🗑️ Removed
|
|
32
|
+
- Removed `subagents.batchSize` configuration option (orchestration now handled by Opus intelligence)
|
|
33
|
+
- Removed `analyzeCodeParallel()` function from `claude-client.js` (replaced by orchestration-driven parallel execution)
|
|
34
|
+
|
|
35
|
+
|
|
8
36
|
## [2.19.0] - 2026-03-06
|
|
9
37
|
|
|
10
38
|
### ✨ Added
|
package/CLAUDE.md
CHANGED
|
@@ -63,13 +63,15 @@ claude-git-hooks/
|
|
|
63
63
|
│ │ ├── telemetry-cmd.js # Telemetry commands - show/clear statistics
|
|
64
64
|
│ │ ├── bump-version.js # Version management - bump with commit, CHANGELOG and tags
|
|
65
65
|
│ │ ├── generate-changelog.js # CHANGELOG generation - standalone command
|
|
66
|
+
│ │ ├── diff-batch-info.js # Batch info - orchestration config + speed telemetry (v2.20.0)
|
|
66
67
|
│ │ └── help.js # Help, AI help, and report-issue commands
|
|
67
68
|
│ ├── hooks/ # Git hooks - Node.js implementations
|
|
68
69
|
│ │ ├── pre-commit.js # Pre-commit analysis - code quality gate
|
|
69
70
|
│ │ └── prepare-commit-msg.js # Message generation - auto commit messages
|
|
70
71
|
│ └── utils/ # Reusable modules - shared logic
|
|
71
|
-
│ ├── analysis-engine.js # Shared analysis logic - file data,
|
|
72
|
-
│ ├──
|
|
72
|
+
│ ├── analysis-engine.js # Shared analysis logic - file data, 3-tier routing, results (v2.13.0+)
|
|
73
|
+
│ ├── diff-analysis-orchestrator.js # Intelligent batch orchestration via Opus (v2.20.0)
|
|
74
|
+
│ ├── claude-client.js # Claude CLI wrapper - spawn, retry, model override
|
|
73
75
|
│ ├── prompt-builder.js # Prompt construction - load templates, replace vars
|
|
74
76
|
│ ├── git-operations.js # Git abstractions - staged files, diff, repo root, push, commit
|
|
75
77
|
│ ├── file-utils.js # File operations - repo-relative paths
|
|
@@ -80,6 +82,7 @@ claude-git-hooks/
|
|
|
80
82
|
│ ├── github-client.js # GitHub helpers - CODEOWNERS parsing, reviewers
|
|
81
83
|
│ ├── task-id.js # Task ID extraction - Jira, GitHub, Linear patterns
|
|
82
84
|
│ ├── interactive-ui.js # CLI UI components - previews, prompts, spinners
|
|
85
|
+
│ ├── judge.js # Auto-fix judge - LLM verdict + search/replace fixes (v2.20.0)
|
|
83
86
|
│ ├── resolution-prompt.js # Issue resolution - AI-friendly fix prompts
|
|
84
87
|
│ ├── installation-diagnostics.js # Installation diagnostics - error context
|
|
85
88
|
│ ├── claude-diagnostics.js # Claude errors - rate limit, auth, formatting
|
|
@@ -95,9 +98,10 @@ claude-git-hooks/
|
|
|
95
98
|
│ ├── check-version.sh # Version check - auto-update prompt
|
|
96
99
|
│ ├── CLAUDE_PRE_COMMIT.md # Analysis criteria - evaluation guidelines
|
|
97
100
|
│ ├── CLAUDE_ANALYSIS_PROMPT.md # Analysis prompt - code review template
|
|
98
|
-
│ ├── CLAUDE_RESOLUTION_PROMPT.md # Resolution prompt -
|
|
101
|
+
│ ├── CLAUDE_RESOLUTION_PROMPT.md # Resolution prompt - structured JSON output for judge + manual use
|
|
99
102
|
│ ├── ANALYZE_DIFF.md # PR analysis - diff review template
|
|
100
103
|
│ ├── GENERATE_CHANGELOG.md # CHANGELOG generation - commit analysis template (v2.12.0)
|
|
104
|
+
│ ├── DIFF_ANALYSIS_ORCHESTRATION_PROMPT.md # Orchestration prompt - Opus batch grouping (v2.20.0)
|
|
101
105
|
│ ├── HELP_QUERY.md # AI help - question answering with NEED_MORE_CONTEXT protocol (v2.18.0)
|
|
102
106
|
│ ├── HELP_REPORT_ISSUE.md # Report issue - question generation from templates (v2.18.0)
|
|
103
107
|
│ ├── HELP_COMPOSE_ISSUE.md # Report issue - issue body composition from answers (v2.18.0)
|
|
@@ -126,8 +130,9 @@ lib/utils/git-operations.js → getStagedFiles()
|
|
|
126
130
|
lib/utils/file-operations.js → filterFiles()
|
|
127
131
|
↓ (builds file data + runs analysis)
|
|
128
132
|
lib/utils/analysis-engine.js → buildFilesData(), runAnalysis()
|
|
129
|
-
↓ (
|
|
130
|
-
lib/utils/
|
|
133
|
+
↓ (2-tier routing: 1-2 files→sequential, 3+→Opus orchestration)
|
|
134
|
+
lib/utils/diff-analysis-orchestrator.js → orchestrateBatches() [if N ≥ 3]
|
|
135
|
+
lib/utils/claude-client.js → analyzeCode(prompt, { model }) per batch [parallel]
|
|
131
136
|
↓ (displays results)
|
|
132
137
|
lib/utils/analysis-engine.js → displayResults()
|
|
133
138
|
↓ (if blocking issues found)
|
|
@@ -165,23 +170,34 @@ preset config (.claude/presets/{name}/config.json) ← HIGHEST PRIORITY
|
|
|
165
170
|
"verifyRemote": true // Verify remote exists (v2.11.0)
|
|
166
171
|
}
|
|
167
172
|
},
|
|
168
|
-
"subagents": { "batchSize": 2 }
|
|
169
173
|
}
|
|
170
174
|
}
|
|
171
175
|
```
|
|
172
176
|
|
|
173
|
-
**Hardcoded defaults (v2.8.0):**
|
|
177
|
+
**Hardcoded defaults (v2.8.0+):**
|
|
174
178
|
|
|
175
|
-
| Parameter
|
|
176
|
-
|
|
|
177
|
-
| Max file size
|
|
178
|
-
| Max files per commit
|
|
179
|
-
|
|
|
180
|
-
|
|
|
181
|
-
|
|
|
182
|
-
| Analysis timeout
|
|
183
|
-
| Commit msg timeout
|
|
184
|
-
| PR metadata timeout
|
|
179
|
+
| Parameter | Value | Notes |
|
|
180
|
+
| ----------------------- | ------- | -------------------------------------------------- |
|
|
181
|
+
| Max file size | 1MB | Files larger are skipped |
|
|
182
|
+
| Max files per commit | 30 | Excess files trigger warning |
|
|
183
|
+
| Orchestrator threshold | 3 files | Commits with ≥3 files use Opus orchestration |
|
|
184
|
+
| Orchestrator model | opus | Internal constant — not user-configurable |
|
|
185
|
+
| Orchestrator timeout | 60s | Lightweight call (file overview only) |
|
|
186
|
+
| Analysis timeout | 300s | Per-batch timeout |
|
|
187
|
+
| Commit msg timeout | 300s | Message generation timeout |
|
|
188
|
+
| PR metadata timeout | 180s | Engine default (reads config) |
|
|
189
|
+
| Judge model | opus | Default, configurable via `config.judge.model` |
|
|
190
|
+
| Judge timeout | 120s | Per-judge call timeout |
|
|
191
|
+
|
|
192
|
+
**Judge behavior (v2.20.0):**
|
|
193
|
+
|
|
194
|
+
- Enabled by default (`config.judge?.enabled !== false`)
|
|
195
|
+
- Runs on **all issues** (any severity), not just blockers
|
|
196
|
+
- **Any unresolved issue blocks the commit** — no issue passes without judge approval
|
|
197
|
+
- Judge failure (timeout, JSON parse error, module load) → user warned → commit blocked
|
|
198
|
+
- No retries — failed fixes stay as unresolved issues
|
|
199
|
+
- When disabled (`config.judge.enabled: false`), falls back to original quality gate (blocks on CRITICAL/BLOCKER only)
|
|
200
|
+
- Resolution prompt file is only generated if issues remain after the judge
|
|
185
201
|
|
|
186
202
|
**3. Presets System**
|
|
187
203
|
|
|
@@ -194,21 +210,36 @@ preset config (.claude/presets/{name}/config.json) ← HIGHEST PRIORITY
|
|
|
194
210
|
| `ai` | `.js`, `.json`, `.md`, `.sh` | Node.js + Claude API | Prompts, API key security, cross-platform |
|
|
195
211
|
| `default` | `.js`, `.sh`, `.py`, `.rb`, `.pl`, `.sql`, `.yaml`, `.json`, `.xml`, `.md` | Multiple | Quality and security fundamentals |
|
|
196
212
|
|
|
197
|
-
**4.
|
|
213
|
+
**4. Analysis Routing (v2.20.0)**
|
|
214
|
+
|
|
215
|
+
Three-tier strategy based on file count:
|
|
198
216
|
|
|
199
|
-
|
|
217
|
+
| Files | Strategy |
|
|
218
|
+
|-------|----------|
|
|
219
|
+
| 1–2 | Sequential — single Claude call |
|
|
220
|
+
| **3+** | **Intelligent orchestration** — Opus orchestrator, semantic grouping, per-batch model, shared context |
|
|
221
|
+
|
|
222
|
+
**Orchestration flow (3+ files):**
|
|
200
223
|
|
|
201
224
|
```
|
|
202
|
-
|
|
225
|
+
staged files (N ≥ 3)
|
|
226
|
+
↓
|
|
227
|
+
[ORCHESTRATOR — Opus, 60s timeout]
|
|
228
|
+
Input: file overview table + detected cross-file deps (JS/TS/Java/Python regex)
|
|
229
|
+
Output: { batches: [{ filePaths, rationale, model }] }
|
|
203
230
|
↓
|
|
204
|
-
|
|
205
|
-
|
|
231
|
+
For each batch:
|
|
232
|
+
→ buildAnalysisPrompt(batchFiles + commonContext + batchRationale)
|
|
233
|
+
→ analyzeCode(prompt, { model: batch.model }) ← per-batch model
|
|
234
|
+
[all batches run in parallel via Promise.all]
|
|
206
235
|
↓
|
|
207
|
-
|
|
236
|
+
consolidateResults()
|
|
208
237
|
```
|
|
209
238
|
|
|
210
|
-
- **
|
|
211
|
-
- **
|
|
239
|
+
- **Orchestration model**: `opus` — hardcoded internal constant, not user-configurable
|
|
240
|
+
- **Threshold**: `ORCHESTRATOR_THRESHOLD = 3` — internal constant in `analysis-engine.js`
|
|
241
|
+
- **Fallback**: any orchestration failure → one-file-per-batch with haiku
|
|
242
|
+
- **Common context**: each batch prompt prefixed with commit overview, dep graph, and batch rationale
|
|
212
243
|
|
|
213
244
|
### Key Module Exports
|
|
214
245
|
|
|
@@ -230,6 +261,7 @@ Wait for both → consolidate results
|
|
|
230
261
|
| `migrate-config.js` | Config migration | `runMigrateConfig()` |
|
|
231
262
|
| `debug.js` | Debug toggle | `runSetDebug()` |
|
|
232
263
|
| `telemetry-cmd.js` | Telemetry commands | `runShowTelemetry()`, `runClearTelemetry()` |
|
|
264
|
+
| `diff-batch-info.js` | Batch info display | `runDiffBatchInfo()` |
|
|
233
265
|
| `help.js` | Help, AI help, report-issue | `runShowHelp()`, `showStaticHelp()`, `runShowVersion()` |
|
|
234
266
|
|
|
235
267
|
**Utility Modules (`lib/utils/`):**
|
|
@@ -238,9 +270,10 @@ Wait for both → consolidate results
|
|
|
238
270
|
| ------------------------ | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
239
271
|
| `lib/cli-metadata.js` | Command registry | `commands`, `buildCommandMap()`, `generateCompletionData()`, `PRESET_NAMES`, `HOOK_NAMES`, `BUMP_TYPES` |
|
|
240
272
|
| `lib/config.js` | Config system | `getConfig()` |
|
|
241
|
-
| `analysis-engine.js` | Shared analysis logic | `buildFileData()`, `buildFilesData()`, `runAnalysis()`, `consolidateResults()`, `hasBlockingIssues()`, `hasAnyIssues()`, `displayResults()`, `displayIssueSummary()` (v2.13.0) |
|
|
242
|
-
| `
|
|
243
|
-
| `
|
|
273
|
+
| `analysis-engine.js` | Shared analysis logic | `buildFileData()`, `buildFilesData()`, `runAnalysis()`, `consolidateResults()`, `hasBlockingIssues()`, `hasAnyIssues()`, `displayResults()`, `displayIssueSummary()` (v2.13.0+) |
|
|
274
|
+
| `diff-analysis-orchestrator.js` | Intelligent batch orchestration | `orchestrateBatches()`, `buildFileOverview()`, `detectDependencies()` (v2.20.0) |
|
|
275
|
+
| `claude-client.js` | Claude CLI wrapper | `analyzeCode()`, `executeClaudeWithRetry()`, `extractJSON()` — spawn, retry, model override |
|
|
276
|
+
| `prompt-builder.js` | Prompt construction | `buildAnalysisPrompt()`, `loadPrompt()` — accepts `commonContext`, `batchRationale` |
|
|
244
277
|
| `git-operations.js` | Git abstractions | `getStagedFiles()`, `getUnstagedFiles()`, `getAllTrackedFiles()`, `getDiff()`, `getRepoRoot()`, `getBranchPushStatus()`, `pushBranch()`, `createCommit()`, `fetchRemote()`, `branchExists()`, `getRemoteBranches()`, `resolveBaseBranch()`, `getChangedFilesBetweenRefs()`, `getDiffBetweenRefs()`, `getCommitsBetweenRefs()` |
|
|
245
278
|
| `file-utils.js` | File operations | `ensureDir()`, `ensureOutputDir()`, `writeOutputFile()`, `walkDirectoryTree()` |
|
|
246
279
|
| `pr-metadata-engine.js` | PR metadata generation | `getBranchContext()`, `buildDiffPayload()`, `generatePRMetadata()`, `analyzeBranchForPR()` (v2.14.0) |
|
|
@@ -252,6 +285,7 @@ Wait for both → consolidate results
|
|
|
252
285
|
| `preset-loader.js` | Preset system | `loadPreset()`, `listPresets()` |
|
|
253
286
|
| `task-id.js` | Task ID extraction | `getOrPromptTaskId()`, `formatWithTaskId()` |
|
|
254
287
|
| `logger.js` | Logging system | `info()`, `warning()`, `error()`, `debug()` |
|
|
288
|
+
| `judge.js` | Auto-fix judge | `judgeAndFix()`, `applyFix()` — LLM verdict + search/replace fixes (v2.20.0) |
|
|
255
289
|
| `resolution-prompt.js` | Issue resolution | `generateResolutionPrompt()` |
|
|
256
290
|
| `interactive-ui.js` | CLI UI components | `showPRPreview()`, `promptConfirmation()`, `promptMenu()`, `promptToggleList()`, `promptEditField()`, `promptUserConfirmation()` |
|
|
257
291
|
| `telemetry.js` | Local telemetry | `recordEvent()`, `displayStatistics()` |
|
|
@@ -262,9 +296,10 @@ Wait for both → consolidate results
|
|
|
262
296
|
2. **Command Pattern**: `lib/commands/*.js` - each CLI command is a self-contained module
|
|
263
297
|
3. **Factory Pattern**: `preset-loader.js` loads configurations dynamically per tech-stack
|
|
264
298
|
4. **Template Method**: `prompt-builder.js` builds prompts from markdown templates
|
|
265
|
-
5. **Strategy Pattern**: `
|
|
266
|
-
6. **
|
|
267
|
-
7. **
|
|
299
|
+
5. **Strategy Pattern**: `analysis-engine.js` selects between sequential (1–2 files) or orchestrated (3+ files) analysis based on file count threshold
|
|
300
|
+
6. **Orchestrator Pattern**: `diff-analysis-orchestrator.js` — Opus decides semantic grouping and model assignment; workers (analyzeCode per batch) execute in parallel
|
|
301
|
+
7. **Adapter Pattern**: `git-operations.js` abstracts git commands into JS functions
|
|
302
|
+
8. **Singleton Pattern**: `config.js` loads configuration once per execution
|
|
268
303
|
|
|
269
304
|
### Key Data Flows
|
|
270
305
|
|
|
@@ -275,9 +310,15 @@ git commit
|
|
|
275
310
|
→ hook reads staged files
|
|
276
311
|
→ filters by preset extensions
|
|
277
312
|
→ builds prompt with diff
|
|
278
|
-
→ Claude analyzes → detects
|
|
279
|
-
→
|
|
280
|
-
|
|
313
|
+
→ Claude analyzes → detects issues
|
|
314
|
+
→ judge evaluates ALL issues (any severity):
|
|
315
|
+
→ TRUE_ISSUE: applies search/replace fix + git add
|
|
316
|
+
→ FALSE_POSITIVE: dismissed
|
|
317
|
+
→ if ALL resolved: exit 0 → COMMIT PROCEEDS
|
|
318
|
+
→ if ANY unresolved: generates resolution prompt → exit 1 → COMMIT BLOCKED
|
|
319
|
+
→ if judge fails (timeout, parse error): user warned → exit 1 → COMMIT BLOCKED
|
|
320
|
+
→ judge disabled (config.judge.enabled: false):
|
|
321
|
+
→ falls back to original quality gate (blocks on CRITICAL/BLOCKER only)
|
|
281
322
|
```
|
|
282
323
|
|
|
283
324
|
**Flow 1.5: Interactive analysis command (v2.13.0)**
|
|
@@ -648,6 +689,9 @@ claude-hooks generate-changelog # Generate CHANGELOG only
|
|
|
648
689
|
claude-hooks help "how do presets work?" # AI-powered help (uses CLAUDE.md)
|
|
649
690
|
claude-hooks help --report-issue # Interactive issue creation
|
|
650
691
|
|
|
692
|
+
# Orchestration diagnostics
|
|
693
|
+
claude-hooks batch-info # Orchestration config + per-model speed telemetry
|
|
694
|
+
|
|
651
695
|
# Debugging
|
|
652
696
|
claude-hooks --debug true # Enable debug mode
|
|
653
697
|
claude-hooks --debug false # Disable debug mode
|
package/README.md
CHANGED
|
@@ -218,6 +218,14 @@ claude-hooks help --report-issue # Interactive GitHub issue creation
|
|
|
218
218
|
claude-hooks --help # Static command reference
|
|
219
219
|
```
|
|
220
220
|
|
|
221
|
+
### Batch Info
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
claude-hooks batch-info
|
|
225
|
+
# Shows: orchestration model, threshold, default analysis model
|
|
226
|
+
# Shows: per-model average analysis time and orchestration overhead (from telemetry)
|
|
227
|
+
```
|
|
228
|
+
|
|
221
229
|
### Other Commands
|
|
222
230
|
|
|
223
231
|
```bash
|
|
@@ -262,6 +270,7 @@ claude-hooks update # Update to latest version
|
|
|
262
270
|
| `migrate-config.js` | **Config migration** - legacy to v2.8.0 format | `runMigrateConfig()` |
|
|
263
271
|
| `debug.js` | **Debug toggle** - enable/disable verbose logging | `runSetDebug()` |
|
|
264
272
|
| `telemetry-cmd.js` | **Telemetry commands** - show/clear statistics | `runShowTelemetry()`, `runClearTelemetry()` |
|
|
273
|
+
| `diff-batch-info.js` | **Batch info** - orchestration config + per-model speed telemetry | `runDiffBatchInfo()` |
|
|
265
274
|
| `help.js` | **Help, AI help, report-issue** | `runShowHelp()`, `showStaticHelp()`, `runShowVersion()` |
|
|
266
275
|
|
|
267
276
|
### Utility Modules (`lib/utils/`)
|
|
@@ -269,14 +278,16 @@ claude-hooks update # Update to latest version
|
|
|
269
278
|
| Module | Purpose | Key Exports |
|
|
270
279
|
|--------|---------|-------------|
|
|
271
280
|
| `analysis-engine.js` | **Shared analysis logic** - file data, orchestration, results (v2.13.0) | `buildFilesData()`, `runAnalysis()`, `consolidateResults()`, `displayResults()` |
|
|
272
|
-
| `
|
|
273
|
-
| `
|
|
281
|
+
| `diff-analysis-orchestrator.js` | **Intelligent orchestration** - semantic batch grouping via Opus (v2.20.0) | `orchestrateBatches()`, `buildFileOverview()`, `detectDependencies()` |
|
|
282
|
+
| `claude-client.js` | **Claude CLI wrapper** - spawn, retry, model override | `analyzeCode()`, `executeClaudeWithRetry()`, `extractJSON()` |
|
|
283
|
+
| `prompt-builder.js` | **Prompt construction** - load templates, replace variables, inject commit context | `buildAnalysisPrompt()`, `loadPrompt()` |
|
|
274
284
|
| `git-operations.js` | **Git abstractions** - staged files, diff, branch comparison | `getStagedFiles()`, `getDiff()`, `getRepoRoot()`, `resolveBaseBranch()`, `getDiffBetweenRefs()` |
|
|
275
285
|
| `pr-metadata-engine.js` | **PR metadata generation** - branch context, diff reduction (v2.14.0) | `getBranchContext()`, `buildDiffPayload()`, `generatePRMetadata()`, `analyzeBranchForPR()` |
|
|
276
286
|
| `github-api.js` | **Octokit integration** - PR creation, token validation, content fetching | `createPullRequest()`, `validateToken()`, `saveGitHubToken()`, `fetchFileContent()`, `fetchDirectoryListing()`, `createIssue()` |
|
|
277
287
|
| `github-client.js` | **GitHub helpers** - CODEOWNERS parsing, reviewers | `getReviewersForFiles()`, `parseGitHubRepo()` |
|
|
278
288
|
| `preset-loader.js` | **Preset system** - load tech-stack configurations | `loadPreset()`, `listPresets()` |
|
|
279
289
|
| `task-id.js` | **Task ID extraction** - Jira, GitHub, Linear patterns | `getOrPromptTaskId()`, `formatWithTaskId()` |
|
|
290
|
+
| `judge.js` | **Auto-fix judge** - LLM verdict + search/replace fixes (v2.20.0) | `judgeAndFix()`, `applyFix()` |
|
|
280
291
|
| `resolution-prompt.js` | **Issue resolution** - AI-friendly fix prompts | `generateResolutionPrompt()` |
|
|
281
292
|
| `logger.js` | **Logging system** - centralized output with debug mode | `info()`, `warning()`, `error()`, `debug()` |
|
|
282
293
|
| `interactive-ui.js` | **CLI UI components** - previews, prompts, spinners | `showPRPreview()`, `promptConfirmation()`, `promptMenu()` |
|
|
@@ -292,9 +303,13 @@ git commit → templates/pre-commit (bash wrapper)
|
|
|
292
303
|
→ getStagedFiles() → filterFiles() by preset extensions + size
|
|
293
304
|
→ buildFilesData() → runAnalysis() (via analysis-engine.js)
|
|
294
305
|
→ displayResults() → show quality gate status
|
|
295
|
-
→
|
|
296
|
-
|
|
297
|
-
|
|
306
|
+
→ judge evaluates ALL issues (any severity):
|
|
307
|
+
→ TRUE_ISSUE: auto-fix via search/replace + git add
|
|
308
|
+
→ FALSE_POSITIVE: dismissed
|
|
309
|
+
→ ALL resolved: exit 0 (pass)
|
|
310
|
+
→ ANY unresolved: generates resolution prompt → exit 1 (block)
|
|
311
|
+
→ judge failure: user warned → exit 1 (block)
|
|
312
|
+
→ judge disabled: original quality gate (blocks on critical/blocker only)
|
|
298
313
|
```
|
|
299
314
|
|
|
300
315
|
**Note:** For interactive review of non-blocking issues, use `claude-hooks analyze` before committing.
|
|
@@ -350,7 +365,6 @@ Preset always wins - tech-stack specific has priority over user preferences.
|
|
|
350
365
|
"verifyRemote": true // Verify remote exists (v2.11.0)
|
|
351
366
|
}
|
|
352
367
|
},
|
|
353
|
-
"subagents": { "batchSize": 2 }
|
|
354
368
|
}
|
|
355
369
|
}
|
|
356
370
|
```
|
|
@@ -359,7 +373,7 @@ Preset always wins - tech-stack specific has priority over user preferences.
|
|
|
359
373
|
|
|
360
374
|
- **Factory**: `preset-loader.js` - dynamic config per tech-stack
|
|
361
375
|
- **Template Method**: `prompt-builder.js` - prompts from .md templates
|
|
362
|
-
- **Strategy**: `
|
|
376
|
+
- **Strategy**: `analysis-engine.js` - sequential vs orchestrated analysis
|
|
363
377
|
- **Adapter**: `git-operations.js` - git commands to JS functions
|
|
364
378
|
- **Command**: `lib/commands/*.js` - one module per CLI command
|
|
365
379
|
|
|
@@ -377,6 +391,9 @@ Preset always wins - tech-stack specific has priority over user preferences.
|
|
|
377
391
|
| Config defaults | `lib/config.js` |
|
|
378
392
|
| GitHub integration | `lib/utils/github-api.js` |
|
|
379
393
|
| Claude CLI calls | `lib/utils/claude-client.js` |
|
|
394
|
+
| Batch orchestration logic | `lib/utils/diff-analysis-orchestrator.js` |
|
|
395
|
+
| Orchestration prompt | `templates/DIFF_ANALYSIS_ORCHESTRATION_PROMPT.md` |
|
|
396
|
+
| Auto-fix judge logic | `lib/utils/judge.js` |
|
|
380
397
|
|
|
381
398
|
### File Structure
|
|
382
399
|
|
|
@@ -397,33 +414,50 @@ claude-git-hooks/
|
|
|
397
414
|
│ │ ├── migrate-config.js # Migration - legacy to v2.8.0
|
|
398
415
|
│ │ ├── debug.js # Debug mode - toggle verbose
|
|
399
416
|
│ │ ├── telemetry-cmd.js # Telemetry - show/clear stats
|
|
417
|
+
│ │ ├── diff-batch-info.js # Batch info - orchestration config
|
|
400
418
|
│ │ └── help.js # Help display - usage info
|
|
401
419
|
│ ├── hooks/ # Git hooks - Node.js logic
|
|
402
420
|
│ │ ├── pre-commit.js # Pre-commit analysis
|
|
403
421
|
│ │ └── prepare-commit-msg.js # Message generation
|
|
404
422
|
│ └── utils/ # Reusable modules - shared logic
|
|
423
|
+
│ ├── diff-analysis-orchestrator.js # Intelligent batch orchestration
|
|
424
|
+
│ └── judge.js # Auto-fix judge (v2.20.0)
|
|
405
425
|
├── templates/
|
|
406
426
|
│ ├── pre-commit # Bash wrapper - invokes Node.js
|
|
407
427
|
│ ├── prepare-commit-msg # Bash wrapper - invokes Node.js
|
|
408
|
-
│ ├──
|
|
428
|
+
│ ├── DIFF_ANALYSIS_ORCHESTRATION_PROMPT.md # Opus orchestration prompt
|
|
429
|
+
│ ├── *.md # Other prompt templates
|
|
409
430
|
│ └── presets/ # Preset configurations
|
|
410
431
|
└── test/unit/ # Jest tests
|
|
411
432
|
```
|
|
412
433
|
|
|
413
|
-
###
|
|
434
|
+
### Analysis Routing (v2.20.0)
|
|
435
|
+
|
|
436
|
+
Two-tier strategy based on file count:
|
|
414
437
|
|
|
415
|
-
Files
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
438
|
+
| Files | Strategy | Details |
|
|
439
|
+
|-------|----------|---------|
|
|
440
|
+
| 1–2 | Sequential | Single Claude call, full context |
|
|
441
|
+
| 3+ | **Intelligent orchestration** | Opus groups files semantically, assigns model per batch, shared commit context |
|
|
442
|
+
|
|
443
|
+
**Orchestration flow (3+ files):**
|
|
444
|
+
1. Opus reads a lightweight file overview + detected cross-file dependencies
|
|
445
|
+
2. Groups related files into semantically coherent batches
|
|
446
|
+
3. Assigns model per batch: `haiku` (config/docs), `sonnet` (business logic), `opus` (security-critical)
|
|
447
|
+
4. All batches run in parallel; each receives a shared commit overview header
|
|
448
|
+
5. Falls back to one-file-per-batch if orchestration fails
|
|
449
|
+
|
|
450
|
+
**Inspect orchestration settings:**
|
|
451
|
+
```bash
|
|
452
|
+
claude-hooks batch-info # Shows config + per-model avg speed from telemetry
|
|
453
|
+
```
|
|
419
454
|
|
|
420
|
-
### Hardcoded Defaults (v2.8.0)
|
|
455
|
+
### Hardcoded Defaults (v2.8.0+)
|
|
421
456
|
|
|
422
457
|
- Max file size: 1MB
|
|
423
|
-
- Max files per commit:
|
|
424
|
-
-
|
|
425
|
-
-
|
|
426
|
-
- Parallel batch size: 3
|
|
458
|
+
- Max files per commit: 30
|
|
459
|
+
- Orchestrator threshold: 3 files
|
|
460
|
+
- Orchestrator model: opus (internal, not configurable)
|
|
427
461
|
|
|
428
462
|
---
|
|
429
463
|
|
package/lib/cli-metadata.js
CHANGED
|
@@ -184,6 +184,11 @@ export const commands = [
|
|
|
184
184
|
'--release': { description: 'Mark as released' }
|
|
185
185
|
}
|
|
186
186
|
},
|
|
187
|
+
{
|
|
188
|
+
name: 'batch-info',
|
|
189
|
+
description: 'Show intelligent diff-analysis orchestration configuration and speed telemetry',
|
|
190
|
+
handler: async () => (await import('./commands/diff-batch-info.js')).runDiffBatchInfo
|
|
191
|
+
},
|
|
187
192
|
{
|
|
188
193
|
name: 'telemetry',
|
|
189
194
|
description: 'View or clear telemetry data',
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File: diff-batch-info.js
|
|
3
|
+
* Purpose: Display intelligent diff-analysis orchestration config and speed telemetry
|
|
4
|
+
*
|
|
5
|
+
* Shows:
|
|
6
|
+
* - Orchestration model and threshold
|
|
7
|
+
* - Default analysis model from config
|
|
8
|
+
* - Per-model avg analysis times from telemetry
|
|
9
|
+
* - Avg orchestration overhead
|
|
10
|
+
* - Overall failure rate
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { getStatistics } from '../utils/telemetry.js';
|
|
14
|
+
import logger from '../utils/logger.js';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Runs the batch-info command
|
|
18
|
+
* Why: Surfaces orchestration configuration and speed telemetry so users can
|
|
19
|
+
* understand the adaptive batch system behavior without needing debug mode.
|
|
20
|
+
*/
|
|
21
|
+
export async function runDiffBatchInfo() {
|
|
22
|
+
console.log(
|
|
23
|
+
'\n╔════════════════════════════════════════════════════════════════════╗'
|
|
24
|
+
);
|
|
25
|
+
console.log(
|
|
26
|
+
'║ INTELLIGENT ANALYSIS ORCHESTRATION INFO ║'
|
|
27
|
+
);
|
|
28
|
+
console.log(
|
|
29
|
+
'╚════════════════════════════════════════════════════════════════════╝\n'
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
console.log('━━━ ORCHESTRATION CONFIGURATION ━━━');
|
|
33
|
+
console.log(' Orchestration model: opus (internal, not user-configurable)');
|
|
34
|
+
console.log(' Orchestrator threshold: 3 files (commits with ≥3 files use intelligent grouping)');
|
|
35
|
+
console.log();
|
|
36
|
+
|
|
37
|
+
console.log('━━━ HOW IT WORKS ━━━');
|
|
38
|
+
console.log(' < 3 files: Sequential analysis (single Claude call)');
|
|
39
|
+
console.log(' ≥ 3 files: Orchestrator groups files semantically,');
|
|
40
|
+
console.log(' assigns model per batch, injects shared context');
|
|
41
|
+
console.log();
|
|
42
|
+
|
|
43
|
+
try {
|
|
44
|
+
const stats = await getStatistics(7);
|
|
45
|
+
|
|
46
|
+
if (!stats.enabled) {
|
|
47
|
+
console.log(' Telemetry is disabled — no speed data available.');
|
|
48
|
+
console.log(
|
|
49
|
+
' To enable, ensure "system.telemetry" is not set to false in .claude/config.json'
|
|
50
|
+
);
|
|
51
|
+
console.log();
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (stats.totalEvents === 0) {
|
|
56
|
+
console.log('━━━ SPEED TELEMETRY (last 7 days) ━━━');
|
|
57
|
+
console.log(' No telemetry data yet.');
|
|
58
|
+
console.log(
|
|
59
|
+
' Run an analysis with ≥3 files to start collecting per-model timing data.'
|
|
60
|
+
);
|
|
61
|
+
console.log();
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
console.log('━━━ SPEED TELEMETRY (last 7 days) ━━━');
|
|
66
|
+
console.log(` Total events: ${stats.totalEvents}`);
|
|
67
|
+
console.log(` Successful batches: ${stats.batchSuccesses}`);
|
|
68
|
+
console.log(` Failure rate: ${stats.failureRate}%`);
|
|
69
|
+
console.log();
|
|
70
|
+
|
|
71
|
+
if (Object.keys(stats.avgAnalysisTimeByModel).length > 0) {
|
|
72
|
+
console.log(' Average analysis time by model:');
|
|
73
|
+
for (const [model, ms] of Object.entries(stats.avgAnalysisTimeByModel)) {
|
|
74
|
+
const seconds = (ms / 1000).toFixed(1);
|
|
75
|
+
console.log(` ${model.padEnd(8)}: ${seconds}s`);
|
|
76
|
+
}
|
|
77
|
+
console.log();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (stats.avgOrchestrationTime > 0) {
|
|
81
|
+
const orchSeconds = (stats.avgOrchestrationTime / 1000).toFixed(1);
|
|
82
|
+
console.log(` Avg orchestration overhead: ${orchSeconds}s`);
|
|
83
|
+
console.log(
|
|
84
|
+
' (Orchestrator call for semantic grouping — one-time per commit)'
|
|
85
|
+
);
|
|
86
|
+
console.log();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (Object.keys(stats.successesByHook).length > 0) {
|
|
90
|
+
console.log(' Successes by hook:');
|
|
91
|
+
for (const [hook, count] of Object.entries(stats.successesByHook)) {
|
|
92
|
+
console.log(` ${hook}: ${count}`);
|
|
93
|
+
}
|
|
94
|
+
console.log();
|
|
95
|
+
}
|
|
96
|
+
} catch (err) {
|
|
97
|
+
logger.debug('diff-batch-info - runDiffBatchInfo', 'Failed to load telemetry', err);
|
|
98
|
+
console.log(' Could not load telemetry data.');
|
|
99
|
+
console.log();
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
console.log('📂 Telemetry files: .claude/telemetry/');
|
|
103
|
+
console.log('💡 Use --debug true to see orchestrator decisions in real time');
|
|
104
|
+
console.log();
|
|
105
|
+
}
|
package/lib/commands/install.js
CHANGED
|
@@ -327,11 +327,6 @@ export function extractLegacySettings(rawConfig) {
|
|
|
327
327
|
}
|
|
328
328
|
}
|
|
329
329
|
|
|
330
|
-
// Subagent batchSize (allowed)
|
|
331
|
-
if (rawConfig.subagents?.batchSize !== undefined) {
|
|
332
|
-
allowedOverrides.subagents = { batchSize: rawConfig.subagents.batchSize };
|
|
333
|
-
}
|
|
334
|
-
|
|
335
330
|
// Advanced params (preserved with warning in manual migration)
|
|
336
331
|
if (rawConfig.analysis?.ignoreExtensions !== undefined) {
|
|
337
332
|
if (!allowedOverrides.analysis) allowedOverrides.analysis = {};
|
|
@@ -343,11 +338,6 @@ export function extractLegacySettings(rawConfig) {
|
|
|
343
338
|
allowedOverrides.commitMessage.taskIdPattern = rawConfig.commitMessage.taskIdPattern;
|
|
344
339
|
}
|
|
345
340
|
|
|
346
|
-
if (rawConfig.subagents?.model !== undefined) {
|
|
347
|
-
if (!allowedOverrides.subagents) allowedOverrides.subagents = {};
|
|
348
|
-
allowedOverrides.subagents.model = rawConfig.subagents.model;
|
|
349
|
-
}
|
|
350
|
-
|
|
351
341
|
return allowedOverrides;
|
|
352
342
|
}
|
|
353
343
|
|
package/lib/config.js
CHANGED
|
@@ -6,9 +6,8 @@
|
|
|
6
6
|
*
|
|
7
7
|
* v2.8.0 Changes:
|
|
8
8
|
* - Removed 21 redundant parameters (hardcoded sensible defaults)
|
|
9
|
-
* - Only
|
|
10
|
-
* -
|
|
11
|
-
* - User can override: github.pr.*, subagents.batchSize
|
|
9
|
+
* - Only 4 user-configurable parameters remain
|
|
10
|
+
* - User can override: github.pr.*
|
|
12
11
|
* - Advanced params moved to config.advanced.example.json
|
|
13
12
|
*
|
|
14
13
|
* User-configurable:
|
|
@@ -16,12 +15,10 @@
|
|
|
16
15
|
* - github.pr.defaultBase
|
|
17
16
|
* - github.pr.reviewers
|
|
18
17
|
* - github.pr.labelRules
|
|
19
|
-
* - subagents.batchSize
|
|
20
18
|
*
|
|
21
19
|
* Advanced (in example file only):
|
|
22
20
|
* - analysis.ignoreExtensions
|
|
23
21
|
* - commitMessage.taskIdPattern
|
|
24
|
-
* - subagents.model
|
|
25
22
|
*/
|
|
26
23
|
|
|
27
24
|
import fs from 'fs';
|
|
@@ -35,7 +32,7 @@ import logger from './utils/logger.js';
|
|
|
35
32
|
const HARDCODED = {
|
|
36
33
|
analysis: {
|
|
37
34
|
maxFileSize: 1000000, // 1MB - sufficient for most files
|
|
38
|
-
maxFiles:
|
|
35
|
+
maxFiles: 30, // Reasonable limit per commit
|
|
39
36
|
timeout: 300000, // 5 minutes - adequate for Claude API
|
|
40
37
|
contextLines: 3, // Git default
|
|
41
38
|
ignoreExtensions: [] // Can be set in advanced config only
|
|
@@ -46,9 +43,7 @@ const HARDCODED = {
|
|
|
46
43
|
taskIdPattern: '([A-Z]{1,3}[-\\s]\\d{3,5})' // Jira/GitHub/Linear pattern
|
|
47
44
|
},
|
|
48
45
|
subagents: {
|
|
49
|
-
enabled: true
|
|
50
|
-
model: 'haiku', // Fast and cost-effective
|
|
51
|
-
batchSize: 3 // Reasonable parallelization
|
|
46
|
+
enabled: true // Enable by default (faster analysis via orchestration)
|
|
52
47
|
},
|
|
53
48
|
templates: {
|
|
54
49
|
baseDir: '.claude/prompts',
|
|
@@ -57,7 +52,6 @@ const HARDCODED = {
|
|
|
57
52
|
commitMessage: 'COMMIT_MESSAGE.md',
|
|
58
53
|
analyzeDiff: 'ANALYZE_DIFF.md',
|
|
59
54
|
resolution: 'CLAUDE_RESOLUTION_PROMPT.md',
|
|
60
|
-
subagentInstruction: 'SUBAGENT_INSTRUCTION.md',
|
|
61
55
|
createGithubPR: 'CREATE_GITHUB_PR.md'
|
|
62
56
|
},
|
|
63
57
|
output: {
|
|
@@ -106,10 +100,6 @@ const defaults = {
|
|
|
106
100
|
}
|
|
107
101
|
},
|
|
108
102
|
|
|
109
|
-
// Subagent configuration (preset can override)
|
|
110
|
-
subagents: {
|
|
111
|
-
batchSize: 3 // Files per parallel batch
|
|
112
|
-
}
|
|
113
103
|
};
|
|
114
104
|
|
|
115
105
|
/**
|
|
@@ -196,8 +186,8 @@ const loadUserConfig = async (baseDir = process.cwd()) => {
|
|
|
196
186
|
|
|
197
187
|
/**
|
|
198
188
|
* Extracts only allowed parameters from legacy config
|
|
199
|
-
*
|
|
200
|
-
* Advanced: analysis.ignoreExtensions, commitMessage.taskIdPattern
|
|
189
|
+
* Allowed: github.pr.*
|
|
190
|
+
* Advanced: analysis.ignoreExtensions, commitMessage.taskIdPattern
|
|
201
191
|
*
|
|
202
192
|
* @param {Object} legacyConfig - Legacy format config
|
|
203
193
|
* @returns {Object} Allowed parameters only
|
|
@@ -219,11 +209,6 @@ const extractAllowedParams = (legacyConfig) => {
|
|
|
219
209
|
}
|
|
220
210
|
}
|
|
221
211
|
|
|
222
|
-
// Subagent batchSize (allowed)
|
|
223
|
-
if (legacyConfig.subagents?.batchSize !== undefined) {
|
|
224
|
-
allowed.subagents = { batchSize: legacyConfig.subagents.batchSize };
|
|
225
|
-
}
|
|
226
|
-
|
|
227
212
|
// Advanced params (allowed but warn)
|
|
228
213
|
if (legacyConfig.analysis?.ignoreExtensions !== undefined) {
|
|
229
214
|
if (!allowed.analysis) allowed.analysis = {};
|
|
@@ -237,12 +222,6 @@ const extractAllowedParams = (legacyConfig) => {
|
|
|
237
222
|
logger.warning('ℹ️ Using advanced parameter: commitMessage.taskIdPattern');
|
|
238
223
|
}
|
|
239
224
|
|
|
240
|
-
if (legacyConfig.subagents?.model !== undefined) {
|
|
241
|
-
if (!allowed.subagents) allowed.subagents = {};
|
|
242
|
-
allowed.subagents.model = legacyConfig.subagents.model;
|
|
243
|
-
logger.warning('ℹ️ Using advanced parameter: subagents.model');
|
|
244
|
-
}
|
|
245
|
-
|
|
246
225
|
return allowed;
|
|
247
226
|
};
|
|
248
227
|
|