claude-git-hooks 2.19.0 → 2.21.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 CHANGED
@@ -5,6 +5,52 @@ 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.21.0] - 2026-03-10
9
+
10
+ ### ✨ Added
11
+ - New `analyze-pr` command to analyze GitHub PRs with team guidelines and post review comments (#86)
12
+ - Linear ticket enrichment for PR analysis - automatically fetches ticket context when `[AUT-1234]` pattern found in PR title
13
+ - New `setup-linear` command for interactive Linear token configuration
14
+ - Centralized token persistence via `token-store.js` utility for managing settings.local.json
15
+ - PR statistics tracking with write-only JSONL analytics at `.claude/statistics/pr/stats.jsonl`
16
+ - Interactive comment workflow for PR analysis - confirm, select, or skip findings before posting
17
+ - Auto-detection of preset from PR labels, Linear ticket labels, or file extensions
18
+ - New `ANALYZE_PR.md` prompt template for GitHub PR review with category injection
19
+ - Category normalization with fuzzy alias mapping for analysis results
20
+
21
+ ### 🔧 Changed
22
+ - Extended `github-api.js` with PR fetch, review creation, and URL parsing capabilities
23
+ - Updated documentation (README, README-NPM, CLAUDE.md) with analyze-pr usage and architecture
24
+
25
+
26
+ ## [2.20.0] - 2026-03-09
27
+
28
+ ### ✨ Added
29
+ - Intelligent batch orchestration for commits with 3+ files using Opus to semantically group files, assign per-batch models, and inject shared commit context
30
+ - 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)
31
+ - New `batch-info` command to display orchestration configuration and per-model average analysis speed from telemetry
32
+ - Per-call model override capability in `analyzeCode()` for different Claude models per analysis batch
33
+ - New `diff-analysis-orchestrator.js` module for semantic batch grouping via Opus
34
+ - New `judge.js` module for LLM verdict and search/replace auto-fixes
35
+ - Cross-file dependency detection for JavaScript, TypeScript, Java, and Python files
36
+ - DIFF_ANALYSIS_ORCHESTRATION_PROMPT.md template for Opus batch grouping
37
+
38
+ ### 🔧 Changed
39
+ - Analysis routing now uses three-tier strategy: 1-2 files use sequential single call, 3+ files trigger intelligent orchestration
40
+ - Judge now runs on all issues regardless of severity (previously only CRITICAL/BLOCKER blocked commits)
41
+ - Resolution prompt file is only generated if issues remain after judge evaluation
42
+ - Updated documentation to clarify that judge blocks commits when any issue remains unresolved
43
+ - Orchestrator threshold set to 3 files as internal constant in `analysis-engine.js`
44
+ - Each batch prompt now includes commit overview, dependency graph, and batch rationale for better cross-file reasoning
45
+ - Judge failures (timeout, JSON parse error, module load) now warn user and block commit
46
+ - Configurable judge model via `config.judge.model` (default: opus)
47
+ - Judge can be disabled via `config.judge.enabled: false` to fall back to original quality gate
48
+
49
+ ### 🗑️ Removed
50
+ - Removed `subagents.batchSize` configuration option (orchestration now handled by Opus intelligence)
51
+ - Removed `analyzeCodeParallel()` function from `claude-client.js` (replaced by orchestration-driven parallel execution)
52
+
53
+
8
54
  ## [2.19.0] - 2026-03-06
9
55
 
10
56
  ### ✨ Added
package/CLAUDE.md CHANGED
@@ -10,7 +10,8 @@
10
10
  2. **Interactive analysis**: `claude-hooks analyze` - review all issues (INFO to BLOCKER) interactively before committing
11
11
  3. **Automatic messages**: Write `git commit -m "auto"` and Claude generates the message in Conventional Commits format with task-id extracted from branch
12
12
  4. **PR analysis**: `claude-hooks analyze-diff [branch]` generates title, description, and test plan for PRs
13
- 5. **PR creation**: `claude-hooks create-pr [branch]` creates the PR on GitHub with automatic metadata (reviewers from CODEOWNERS, labels by preset)
13
+ 5. **PR review**: `claude-hooks analyze-pr <url>` analyzes a GitHub PR with preset guidelines, Linear ticket enrichment, and posts review comments
14
+ 6. **PR creation**: `claude-hooks create-pr [branch]` creates the PR on GitHub with automatic metadata (reviewers from CODEOWNERS, labels by preset)
14
15
 
15
16
  ## Architecture
16
17
 
@@ -54,8 +55,10 @@ claude-git-hooks/
54
55
  │ │ ├── install.js # Install command - dependencies, hooks, templates
55
56
  │ │ ├── hooks.js # Hook management - enable, disable, status, uninstall
56
57
  │ │ ├── analyze-diff.js # Diff analysis - generate PR metadata from git diff
58
+ │ │ ├── analyze-pr.js # PR analysis - analyze GitHub PR with team guidelines
57
59
  │ │ ├── create-pr.js # PR creation - full Octokit workflow
58
60
  │ │ ├── setup-github.js # Token setup - interactive GitHub configuration
61
+ │ │ ├── setup-linear.js # Token setup - interactive Linear configuration
59
62
  │ │ ├── presets.js # Preset management - list, set, show current
60
63
  │ │ ├── update.js # Self-update - check and install latest version
61
64
  │ │ ├── migrate-config.js # Config migration - legacy to v2.8.0 format
@@ -63,23 +66,29 @@ claude-git-hooks/
63
66
  │ │ ├── telemetry-cmd.js # Telemetry commands - show/clear statistics
64
67
  │ │ ├── bump-version.js # Version management - bump with commit, CHANGELOG and tags
65
68
  │ │ ├── generate-changelog.js # CHANGELOG generation - standalone command
69
+ │ │ ├── diff-batch-info.js # Batch info - orchestration config + speed telemetry (v2.20.0)
66
70
  │ │ └── help.js # Help, AI help, and report-issue commands
67
71
  │ ├── hooks/ # Git hooks - Node.js implementations
68
72
  │ │ ├── pre-commit.js # Pre-commit analysis - code quality gate
69
73
  │ │ └── prepare-commit-msg.js # Message generation - auto commit messages
70
74
  │ └── utils/ # Reusable modules - shared logic
71
- │ ├── analysis-engine.js # Shared analysis logic - file data, orchestration, results (v2.13.0)
72
- │ ├── claude-client.js # Claude CLI wrapper - spawn, retry, parallel
75
+ │ ├── analysis-engine.js # Shared analysis logic - file data, 3-tier routing, results (v2.13.0+)
76
+ │ ├── diff-analysis-orchestrator.js # Intelligent batch orchestration via Opus (v2.20.0)
77
+ │ ├── claude-client.js # Claude CLI wrapper - spawn, retry, model override
73
78
  │ ├── prompt-builder.js # Prompt construction - load templates, replace vars
74
79
  │ ├── git-operations.js # Git abstractions - staged files, diff, repo root, push, commit
75
80
  │ ├── file-utils.js # File operations - repo-relative paths
76
81
  │ ├── logger.js # Logging system - centralized output, debug mode
77
82
  │ ├── preset-loader.js # Preset system - load tech-stack configurations
78
83
  │ ├── pr-metadata-engine.js # PR metadata generation - branch context, diff reduction, metadata (v2.14.0)
79
- │ ├── github-api.js # Octokit integration - PR creation, token validation
84
+ │ ├── github-api.js # Octokit integration - PR creation, PR analysis, token validation
80
85
  │ ├── github-client.js # GitHub helpers - CODEOWNERS parsing, reviewers
86
+ │ ├── token-store.js # Token persistence - centralized settings.local.json read/write
87
+ │ ├── linear-connector.js # Linear API - ticket context fetching with retry
88
+ │ ├── pr-statistics.js # PR statistics - write-only JSONL analytics
81
89
  │ ├── task-id.js # Task ID extraction - Jira, GitHub, Linear patterns
82
90
  │ ├── interactive-ui.js # CLI UI components - previews, prompts, spinners
91
+ │ ├── judge.js # Auto-fix judge - LLM verdict + search/replace fixes (v2.20.0)
83
92
  │ ├── resolution-prompt.js # Issue resolution - AI-friendly fix prompts
84
93
  │ ├── installation-diagnostics.js # Installation diagnostics - error context
85
94
  │ ├── claude-diagnostics.js # Claude errors - rate limit, auth, formatting
@@ -95,9 +104,11 @@ claude-git-hooks/
95
104
  │ ├── check-version.sh # Version check - auto-update prompt
96
105
  │ ├── CLAUDE_PRE_COMMIT.md # Analysis criteria - evaluation guidelines
97
106
  │ ├── CLAUDE_ANALYSIS_PROMPT.md # Analysis prompt - code review template
98
- │ ├── CLAUDE_RESOLUTION_PROMPT.md # Resolution prompt - issue fix template
107
+ │ ├── CLAUDE_RESOLUTION_PROMPT.md # Resolution prompt - structured JSON output for judge + manual use
99
108
  │ ├── ANALYZE_DIFF.md # PR analysis - diff review template
109
+ │ ├── ANALYZE_PR.md # PR analysis - GitHub PR review template with category injection
100
110
  │ ├── GENERATE_CHANGELOG.md # CHANGELOG generation - commit analysis template (v2.12.0)
111
+ │ ├── DIFF_ANALYSIS_ORCHESTRATION_PROMPT.md # Orchestration prompt - Opus batch grouping (v2.20.0)
101
112
  │ ├── HELP_QUERY.md # AI help - question answering with NEED_MORE_CONTEXT protocol (v2.18.0)
102
113
  │ ├── HELP_REPORT_ISSUE.md # Report issue - question generation from templates (v2.18.0)
103
114
  │ ├── HELP_COMPOSE_ISSUE.md # Report issue - issue body composition from answers (v2.18.0)
@@ -126,8 +137,9 @@ lib/utils/git-operations.js → getStagedFiles()
126
137
  lib/utils/file-operations.js → filterFiles()
127
138
  ↓ (builds file data + runs analysis)
128
139
  lib/utils/analysis-engine.js → buildFilesData(), runAnalysis()
129
- ↓ (orchestrates parallel/sequential Claude CLI calls)
130
- lib/utils/claude-client.js → analyzeCode() or analyzeCodeParallel()
140
+ ↓ (2-tier routing: 1-2 files→sequential, 3+→Opus orchestration)
141
+ lib/utils/diff-analysis-orchestrator.js → orchestrateBatches() [if N ≥ 3]
142
+ lib/utils/claude-client.js → analyzeCode(prompt, { model }) per batch [parallel]
131
143
  ↓ (displays results)
132
144
  lib/utils/analysis-engine.js → displayResults()
133
145
  ↓ (if blocking issues found)
@@ -165,23 +177,36 @@ preset config (.claude/presets/{name}/config.json) ← HIGHEST PRIORITY
165
177
  "verifyRemote": true // Verify remote exists (v2.11.0)
166
178
  }
167
179
  },
168
- "subagents": { "batchSize": 2 }
169
180
  }
170
181
  }
171
182
  ```
172
183
 
173
- **Hardcoded defaults (v2.8.0):**
174
-
175
- | Parameter | Value | Notes |
176
- | -------------------- | ------- | ---------------------------- |
177
- | Max file size | 1MB | Files larger are skipped |
178
- | Max files per commit | 20 | Excess files trigger warning |
179
- | Parallel analysis | enabled | Always on for 3+ files |
180
- | Parallel model | haiku | Fast, cost-effective |
181
- | Parallel batch size | 3 | Files per Claude process |
182
- | Analysis timeout | 300s | Per-batch timeout |
183
- | Commit msg timeout | 300s | Message generation timeout |
184
- | PR metadata timeout | 180s | Engine default (reads config)|
184
+ **Hardcoded defaults (v2.8.0+):**
185
+
186
+ | Parameter | Value | Notes |
187
+ | ----------------------- | ------- | -------------------------------------------------- |
188
+ | Max file size | 1MB | Files larger are skipped |
189
+ | Max files per commit | 30 | Excess files trigger warning |
190
+ | Orchestrator threshold | 3 files | Commits with 3 files use Opus orchestration |
191
+ | Orchestrator model | opus | Internal constant — not user-configurable |
192
+ | Orchestrator timeout | 60s | Lightweight call (file overview only) |
193
+ | Analysis timeout | 300s | Per-batch timeout |
194
+ | Commit msg timeout | 300s | Message generation timeout |
195
+ | PR metadata timeout | 180s | Engine default (reads config) |
196
+ | Judge model | sonnet | Default, configurable via `config.judge.model` |
197
+ | Judge timeout | 120s | Per-judge call timeout |
198
+ | PR analysis model | sonnet | Default, configurable via `config.prAnalysis.model` |
199
+ | PR analysis timeout | 300s | Per-analysis Claude call |
200
+
201
+ **Judge behavior (v2.20.0):**
202
+
203
+ - Enabled by default (`config.judge?.enabled !== false`)
204
+ - Runs on **all issues** (any severity), not just blockers
205
+ - **Any unresolved issue blocks the commit** — no issue passes without judge approval
206
+ - Judge failure (timeout, JSON parse error, module load) → user warned → commit blocked
207
+ - No retries — failed fixes stay as unresolved issues
208
+ - When disabled (`config.judge.enabled: false`), falls back to original quality gate (blocks on CRITICAL/BLOCKER only)
209
+ - Resolution prompt file is only generated if issues remain after the judge
185
210
 
186
211
  **3. Presets System**
187
212
 
@@ -194,21 +219,36 @@ preset config (.claude/presets/{name}/config.json) ← HIGHEST PRIORITY
194
219
  | `ai` | `.js`, `.json`, `.md`, `.sh` | Node.js + Claude API | Prompts, API key security, cross-platform |
195
220
  | `default` | `.js`, `.sh`, `.py`, `.rb`, `.pl`, `.sql`, `.yaml`, `.json`, `.xml`, `.md` | Multiple | Quality and security fundamentals |
196
221
 
197
- **4. Parallel Analysis (v2.2.0+)**
222
+ **4. Analysis Routing (v2.20.0)**
223
+
224
+ Three-tier strategy based on file count:
225
+
226
+ | Files | Strategy |
227
+ |-------|----------|
228
+ | 1–2 | Sequential — single Claude call |
229
+ | **3+** | **Intelligent orchestration** — Opus orchestrator, semantic grouping, per-batch model, shared context |
198
230
 
199
- When 3+ files are present, the system divides into batches and executes multiple `claude` CLI processes in parallel:
231
+ **Orchestration flow (3+ files):**
200
232
 
201
233
  ```
202
- 4 files + batchSize=2
234
+ staged files (N ≥ 3)
203
235
 
204
- Batch 1: [file1, file2] → claude CLI process #1 (parallel)
205
- Batch 2: [file3, file4] claude CLI process #2 (parallel)
236
+ [ORCHESTRATOR Opus, 60s timeout]
237
+ Input: file overview table + detected cross-file deps (JS/TS/Java/Python regex)
238
+ Output: { batches: [{ filePaths, rationale, model }] }
206
239
 
207
- Wait for both → consolidate results
240
+ For each batch:
241
+ → buildAnalysisPrompt(batchFiles + commonContext + batchRationale)
242
+ → analyzeCode(prompt, { model: batch.model }) ← per-batch model
243
+ [all batches run in parallel via Promise.all]
244
+
245
+ consolidateResults()
208
246
  ```
209
247
 
210
- - **Configuration**: `.claude/config.json` `subagents.batchSize`, `subagents.model` (haiku/sonnet/opus)
211
- - **Speed-up**: ~4x faster with batch=1 (1 file per process)
248
+ - **Orchestration model**: `opus` hardcoded internal constant, not user-configurable
249
+ - **Threshold**: `ORCHESTRATOR_THRESHOLD = 3` internal constant in `analysis-engine.js`
250
+ - **Fallback**: any orchestration failure → one-file-per-batch with haiku
251
+ - **Common context**: each batch prompt prefixed with commit overview, dep graph, and batch rationale
212
252
 
213
253
  ### Key Module Exports
214
254
 
@@ -221,15 +261,18 @@ Wait for both → consolidate results
221
261
  | `hooks.js` | Hook management | `runEnable()`, `runDisable()`, `runStatus()`, `runUninstall()` |
222
262
  | `analyze.js` | Interactive code analysis | `runAnalyze()` |
223
263
  | `analyze-diff.js` | Diff analysis | `runAnalyzeDiff()` |
264
+ | `analyze-pr.js` | PR analysis from URL | `runAnalyzePr()`, `normalizeCategory()` |
224
265
  | `create-pr.js` | PR creation | `runCreatePr()` |
225
266
  | `bump-version.js` | Version management | `runBumpVersion()` |
226
267
  | `generate-changelog.js` | CHANGELOG generation | `runGenerateChangelog()` |
227
- | `setup-github.js` | Token setup | `runSetupGitHub()` |
268
+ | `setup-github.js` | Token setup (GitHub) | `runSetupGitHub()` |
269
+ | `setup-linear.js` | Token setup (Linear) | `runSetupLinear()` |
228
270
  | `presets.js` | Preset management | `runShowPresets()`, `runSetPreset()`, `runCurrentPreset()` |
229
271
  | `update.js` | Self-update | `runUpdate()` |
230
272
  | `migrate-config.js` | Config migration | `runMigrateConfig()` |
231
273
  | `debug.js` | Debug toggle | `runSetDebug()` |
232
274
  | `telemetry-cmd.js` | Telemetry commands | `runShowTelemetry()`, `runClearTelemetry()` |
275
+ | `diff-batch-info.js` | Batch info display | `runDiffBatchInfo()` |
233
276
  | `help.js` | Help, AI help, report-issue | `runShowHelp()`, `showStaticHelp()`, `runShowVersion()` |
234
277
 
235
278
  **Utility Modules (`lib/utils/`):**
@@ -238,20 +281,25 @@ Wait for both → consolidate results
238
281
  | ------------------------ | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
239
282
  | `lib/cli-metadata.js` | Command registry | `commands`, `buildCommandMap()`, `generateCompletionData()`, `PRESET_NAMES`, `HOOK_NAMES`, `BUMP_TYPES` |
240
283
  | `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
- | `claude-client.js` | Claude CLI wrapper | `analyzeCode()`, `analyzeCodeParallel()`, `executeClaudeWithRetry()` |
243
- | `prompt-builder.js` | Prompt construction | `buildAnalysisPrompt()`, `loadPrompt()` |
284
+ | `analysis-engine.js` | Shared analysis logic | `buildFileData()`, `buildFilesData()`, `runAnalysis()`, `consolidateResults()`, `hasBlockingIssues()`, `hasAnyIssues()`, `displayResults()`, `displayIssueSummary()` (v2.13.0+) |
285
+ | `diff-analysis-orchestrator.js` | Intelligent batch orchestration | `orchestrateBatches()`, `buildFileOverview()`, `detectDependencies()` (v2.20.0) |
286
+ | `claude-client.js` | Claude CLI wrapper | `analyzeCode()`, `executeClaudeWithRetry()`, `extractJSON()` — spawn, retry, model override |
287
+ | `prompt-builder.js` | Prompt construction | `buildAnalysisPrompt()`, `loadPrompt()` — accepts `commonContext`, `batchRationale` |
244
288
  | `git-operations.js` | Git abstractions | `getStagedFiles()`, `getUnstagedFiles()`, `getAllTrackedFiles()`, `getDiff()`, `getRepoRoot()`, `getBranchPushStatus()`, `pushBranch()`, `createCommit()`, `fetchRemote()`, `branchExists()`, `getRemoteBranches()`, `resolveBaseBranch()`, `getChangedFilesBetweenRefs()`, `getDiffBetweenRefs()`, `getCommitsBetweenRefs()` |
245
289
  | `file-utils.js` | File operations | `ensureDir()`, `ensureOutputDir()`, `writeOutputFile()`, `walkDirectoryTree()` |
246
290
  | `pr-metadata-engine.js` | PR metadata generation | `getBranchContext()`, `buildDiffPayload()`, `generatePRMetadata()`, `analyzeBranchForPR()` (v2.14.0) |
247
291
  | `git-tag-manager.js` | Git tag operations | `createTag()`, `pushTags()`, `getLocalTags()`, `getRemoteTags()`, `compareLocalAndRemoteTags()`, `tagExists()` (v2.12.0) |
248
292
  | `version-manager.js` | Version management | `discoverVersionFiles()`, `getDiscoveryResult()`, `readVersionFromFile()`, `writeVersionToFile()`, `updateVersionFiles()`, `modifySuffix()`, `incrementVersion()`, `parseVersion()`, `validateVersionFormat()`, `compareVersions()`, `validateVersionAlignment()` (v2.15.5) |
249
293
  | `changelog-generator.js` | CHANGELOG generation | `generateChangelogEntry()`, `updateChangelogFile()`, `getLastFinalVersionTag()`, `getCommitsSinceTag()`, `discoverChangelogFiles()`, `selectChangelogFile()` (v2.12.0) |
250
- | `github-api.js` | Octokit integration | `createPullRequest()`, `validateToken()`, `saveGitHubToken()`, `fetchFileContent()`, `fetchDirectoryListing()`, `createIssue()` |
294
+ | `github-api.js` | Octokit integration | `createPullRequest()`, `fetchPullRequest()`, `fetchPullRequestFiles()`, `createPullRequestReview()`, `parseGitHubPRUrl()`, `validateToken()`, `saveGitHubToken()`, `fetchFileContent()`, `fetchDirectoryListing()`, `createIssue()` |
251
295
  | `github-client.js` | GitHub helpers | `getReviewersForFiles()`, `parseGitHubRepo()` |
296
+ | `token-store.js` | Token persistence | `loadToken()`, `saveToken()`, `hasToken()`, `loadLocalSettings()` |
297
+ | `linear-connector.js` | Linear integration | `loadLinearToken()`, `testConnection()`, `fetchTicket()`, `extractLinearTicketFromTitle()`, `parseLinearIdentifier()`, `LinearConnectorError` |
298
+ | `pr-statistics.js` | PR statistics | `recordPRAnalysis()` — write-only JSONL at `.claude/statistics/pr/stats.jsonl` |
252
299
  | `preset-loader.js` | Preset system | `loadPreset()`, `listPresets()` |
253
300
  | `task-id.js` | Task ID extraction | `getOrPromptTaskId()`, `formatWithTaskId()` |
254
301
  | `logger.js` | Logging system | `info()`, `warning()`, `error()`, `debug()` |
302
+ | `judge.js` | Auto-fix judge | `judgeAndFix()`, `applyFix()` — LLM verdict + search/replace fixes (v2.20.0) |
255
303
  | `resolution-prompt.js` | Issue resolution | `generateResolutionPrompt()` |
256
304
  | `interactive-ui.js` | CLI UI components | `showPRPreview()`, `promptConfirmation()`, `promptMenu()`, `promptToggleList()`, `promptEditField()`, `promptUserConfirmation()` |
257
305
  | `telemetry.js` | Local telemetry | `recordEvent()`, `displayStatistics()` |
@@ -262,9 +310,10 @@ Wait for both → consolidate results
262
310
  2. **Command Pattern**: `lib/commands/*.js` - each CLI command is a self-contained module
263
311
  3. **Factory Pattern**: `preset-loader.js` loads configurations dynamically per tech-stack
264
312
  4. **Template Method**: `prompt-builder.js` builds prompts from markdown templates
265
- 5. **Strategy Pattern**: `claude-client.js` selects between sequential or parallel analysis
266
- 6. **Adapter Pattern**: `git-operations.js` abstracts git commands into JS functions
267
- 7. **Singleton Pattern**: `config.js` loads configuration once per execution
313
+ 5. **Strategy Pattern**: `analysis-engine.js` selects between sequential (1–2 files) or orchestrated (3+ files) analysis based on file count threshold
314
+ 6. **Orchestrator Pattern**: `diff-analysis-orchestrator.js` Opus decides semantic grouping and model assignment; workers (analyzeCode per batch) execute in parallel
315
+ 7. **Adapter Pattern**: `git-operations.js` abstracts git commands into JS functions
316
+ 8. **Singleton Pattern**: `config.js` loads configuration once per execution
268
317
 
269
318
  ### Key Data Flows
270
319
 
@@ -275,9 +324,15 @@ git commit
275
324
  → hook reads staged files
276
325
  → filters by preset extensions
277
326
  → builds prompt with diff
278
- → Claude analyzes → detects SQL injection (CRITICAL)
279
- generates resolution prompt
280
- exit 1 COMMIT BLOCKED
327
+ → Claude analyzes → detects issues
328
+ judge evaluates ALL issues (any severity):
329
+ TRUE_ISSUE: applies search/replace fix + git add
330
+ → FALSE_POSITIVE: dismissed
331
+ → if ALL resolved: exit 0 → COMMIT PROCEEDS
332
+ → if ANY unresolved: generates resolution prompt → exit 1 → COMMIT BLOCKED
333
+ → if judge fails (timeout, parse error): user warned → exit 1 → COMMIT BLOCKED
334
+ → judge disabled (config.judge.enabled: false):
335
+ → falls back to original quality gate (blocks on CRITICAL/BLOCKER only)
281
336
  ```
282
337
 
283
338
  **Flow 1.5: Interactive analysis command (v2.13.0)**
@@ -320,6 +375,21 @@ claude-hooks analyze-diff develop
320
375
  → saves to .claude/out/pr-analysis.json
321
376
  ```
322
377
 
378
+ **Flow 3.5: Analyze PR from GitHub URL**
379
+
380
+ ```
381
+ claude-hooks analyze-pr https://github.com/owner/repo/pull/123
382
+ → parseGitHubPRUrl() → { owner, repo, number }
383
+ → fetchPullRequest() + fetchPullRequestFiles() via Octokit
384
+ → extractLinearTicketFromTitle() → fetchTicket() (optional enrichment)
385
+ → resolvePreset(): CLI flag → PR labels → ticket labels → auto-detect from extensions → 'default'
386
+ → loadPrompt('ANALYZE_PR.md') with preset guidelines + category injection
387
+ → executeClaudeWithRetry() → extractJSON() → normalizeCategory() with fuzzy aliases
388
+ → interactive comment workflow: post all / select / skip
389
+ → createPullRequestReview() with inline comments + review body
390
+ → recordPRAnalysis() → .claude/statistics/pr/stats.jsonl
391
+ ```
392
+
323
393
  **Flow 4: PR creation (with auto-push v2.11.0, engine v2.14.0)**
324
394
 
325
395
  ```
@@ -632,8 +702,11 @@ claude-hooks preset current # View current preset
632
702
 
633
703
  # Analysis and PRs
634
704
  claude-hooks analyze-diff [branch] # Analyze diff for PR
705
+ claude-hooks analyze-pr <pr-url> # Analyze GitHub PR with team guidelines
706
+ claude-hooks analyze-pr <url> --dry-run # Analyze without posting comments
635
707
  claude-hooks create-pr [branch] # Create PR on GitHub
636
708
  claude-hooks setup-github # Configure GitHub token
709
+ claude-hooks setup-linear # Configure Linear token
637
710
 
638
711
  # Version management
639
712
  claude-hooks bump-version patch # Bump version (commits, tags locally)
@@ -648,6 +721,9 @@ claude-hooks generate-changelog # Generate CHANGELOG only
648
721
  claude-hooks help "how do presets work?" # AI-powered help (uses CLAUDE.md)
649
722
  claude-hooks help --report-issue # Interactive issue creation
650
723
 
724
+ # Orchestration diagnostics
725
+ claude-hooks batch-info # Orchestration config + per-model speed telemetry
726
+
651
727
  # Debugging
652
728
  claude-hooks --debug true # Enable debug mode
653
729
  claude-hooks --debug false # Disable debug mode
package/README.md CHANGED
@@ -41,10 +41,11 @@ claude-hooks create-pr develop
41
41
  - Prompts for confirmation (configurable)
42
42
  - Handles diverged branches gracefully
43
43
 
44
- ### GitHub Token Setup
44
+ ### Token Setup
45
45
 
46
46
  ```bash
47
- claude-hooks setup-github # Shows status and configuration options
47
+ claude-hooks setup-github # Configure GitHub token for PR creation
48
+ claude-hooks setup-linear # Configure Linear token for ticket enrichment
48
49
  ```
49
50
 
50
51
  **Option 1 - Settings file (recommended):**
@@ -94,6 +95,24 @@ claude-hooks analyze-diff develop
94
95
  # Generates PR metadata without creating
95
96
  ```
96
97
 
98
+ ### Analyze PR from GitHub URL
99
+
100
+ ```bash
101
+ claude-hooks analyze-pr https://github.com/owner/repo/pull/123
102
+ # Fetches PR, applies preset guidelines, posts review comments
103
+
104
+ claude-hooks analyze-pr https://github.com/owner/repo/pull/123 --dry-run
105
+ # Analyze without posting comments
106
+
107
+ claude-hooks analyze-pr https://github.com/owner/repo/pull/123 --preset backend --model opus
108
+ # Override preset and model
109
+ ```
110
+
111
+ - Auto-detects preset from PR labels, Linear ticket labels, or file extensions
112
+ - Enriches with Linear ticket context when `[AUT-1234]` found in PR title
113
+ - Interactive comment workflow: confirm/skip each finding before posting
114
+ - Classifies into inline (file:line) and general (review-level) categories
115
+
97
116
  ### Bump Version
98
117
 
99
118
  Automatic version management with CHANGELOG generation and Git tagging:
@@ -218,6 +237,14 @@ claude-hooks help --report-issue # Interactive GitHub issue creation
218
237
  claude-hooks --help # Static command reference
219
238
  ```
220
239
 
240
+ ### Batch Info
241
+
242
+ ```bash
243
+ claude-hooks batch-info
244
+ # Shows: orchestration model, threshold, default analysis model
245
+ # Shows: per-model average analysis time and orchestration overhead (from telemetry)
246
+ ```
247
+
221
248
  ### Other Commands
222
249
 
223
250
  ```bash
@@ -253,15 +280,18 @@ claude-hooks update # Update to latest version
253
280
  | `hooks.js` | **Hook management** - enable, disable, status, uninstall | `runEnable()`, `runDisable()`, `runStatus()`, `runUninstall()` |
254
281
  | `analyze.js` | **Interactive code analysis** - analyze before committing | `runAnalyze()` |
255
282
  | `analyze-diff.js` | **Diff analysis** - generate PR metadata from git diff | `runAnalyzeDiff()` |
283
+ | `analyze-pr.js` | **PR analysis** - analyze GitHub PR with team guidelines | `runAnalyzePr()` |
256
284
  | `create-pr.js` | **PR creation** - full workflow via Octokit | `runCreatePr()` |
257
285
  | `bump-version.js` | **Version management** - bump with CHANGELOG and Git tag | `runBumpVersion()` |
258
286
  | `generate-changelog.js` | **CHANGELOG generation** - standalone command | `runGenerateChangelog()` |
259
287
  | `setup-github.js` | **Token setup** - interactive GitHub configuration | `runSetupGitHub()` |
288
+ | `setup-linear.js` | **Token setup** - interactive Linear configuration | `runSetupLinear()` |
260
289
  | `presets.js` | **Preset management** - list, set, show current | `runShowPresets()`, `runSetPreset()`, `runCurrentPreset()` |
261
290
  | `update.js` | **Self-update** - check and install latest version | `runUpdate()` |
262
291
  | `migrate-config.js` | **Config migration** - legacy to v2.8.0 format | `runMigrateConfig()` |
263
292
  | `debug.js` | **Debug toggle** - enable/disable verbose logging | `runSetDebug()` |
264
293
  | `telemetry-cmd.js` | **Telemetry commands** - show/clear statistics | `runShowTelemetry()`, `runClearTelemetry()` |
294
+ | `diff-batch-info.js` | **Batch info** - orchestration config + per-model speed telemetry | `runDiffBatchInfo()` |
265
295
  | `help.js` | **Help, AI help, report-issue** | `runShowHelp()`, `showStaticHelp()`, `runShowVersion()` |
266
296
 
267
297
  ### Utility Modules (`lib/utils/`)
@@ -269,14 +299,19 @@ claude-hooks update # Update to latest version
269
299
  | Module | Purpose | Key Exports |
270
300
  |--------|---------|-------------|
271
301
  | `analysis-engine.js` | **Shared analysis logic** - file data, orchestration, results (v2.13.0) | `buildFilesData()`, `runAnalysis()`, `consolidateResults()`, `displayResults()` |
272
- | `claude-client.js` | **Claude CLI wrapper** - spawn, retry, parallel execution | `analyzeCode()`, `analyzeCodeParallel()`, `executeClaudeWithRetry()` |
273
- | `prompt-builder.js` | **Prompt construction** - load templates, replace variables | `buildAnalysisPrompt()`, `loadPrompt()` |
302
+ | `diff-analysis-orchestrator.js` | **Intelligent orchestration** - semantic batch grouping via Opus (v2.20.0) | `orchestrateBatches()`, `buildFileOverview()`, `detectDependencies()` |
303
+ | `claude-client.js` | **Claude CLI wrapper** - spawn, retry, model override | `analyzeCode()`, `executeClaudeWithRetry()`, `extractJSON()` |
304
+ | `prompt-builder.js` | **Prompt construction** - load templates, replace variables, inject commit context | `buildAnalysisPrompt()`, `loadPrompt()` |
274
305
  | `git-operations.js` | **Git abstractions** - staged files, diff, branch comparison | `getStagedFiles()`, `getDiff()`, `getRepoRoot()`, `resolveBaseBranch()`, `getDiffBetweenRefs()` |
275
306
  | `pr-metadata-engine.js` | **PR metadata generation** - branch context, diff reduction (v2.14.0) | `getBranchContext()`, `buildDiffPayload()`, `generatePRMetadata()`, `analyzeBranchForPR()` |
276
- | `github-api.js` | **Octokit integration** - PR creation, token validation, content fetching | `createPullRequest()`, `validateToken()`, `saveGitHubToken()`, `fetchFileContent()`, `fetchDirectoryListing()`, `createIssue()` |
307
+ | `github-api.js` | **Octokit integration** - PR creation, PR analysis, token validation, content fetching | `createPullRequest()`, `fetchPullRequest()`, `fetchPullRequestFiles()`, `createPullRequestReview()`, `parseGitHubPRUrl()`, `validateToken()`, `saveGitHubToken()`, `fetchFileContent()`, `fetchDirectoryListing()`, `createIssue()` |
308
+ | `token-store.js` | **Token persistence** - centralized settings.local.json read/write | `loadToken()`, `saveToken()`, `hasToken()`, `loadLocalSettings()` |
309
+ | `linear-connector.js` | **Linear integration** - ticket context fetching with retry | `fetchTicket()`, `extractLinearTicketFromTitle()`, `testConnection()`, `loadLinearToken()` |
310
+ | `pr-statistics.js` | **PR statistics** - write-only JSONL analytics | `recordPRAnalysis()` |
277
311
  | `github-client.js` | **GitHub helpers** - CODEOWNERS parsing, reviewers | `getReviewersForFiles()`, `parseGitHubRepo()` |
278
312
  | `preset-loader.js` | **Preset system** - load tech-stack configurations | `loadPreset()`, `listPresets()` |
279
313
  | `task-id.js` | **Task ID extraction** - Jira, GitHub, Linear patterns | `getOrPromptTaskId()`, `formatWithTaskId()` |
314
+ | `judge.js` | **Auto-fix judge** - LLM verdict + search/replace fixes (v2.20.0) | `judgeAndFix()`, `applyFix()` |
280
315
  | `resolution-prompt.js` | **Issue resolution** - AI-friendly fix prompts | `generateResolutionPrompt()` |
281
316
  | `logger.js` | **Logging system** - centralized output with debug mode | `info()`, `warning()`, `error()`, `debug()` |
282
317
  | `interactive-ui.js` | **CLI UI components** - previews, prompts, spinners | `showPRPreview()`, `promptConfirmation()`, `promptMenu()` |
@@ -292,9 +327,13 @@ git commit → templates/pre-commit (bash wrapper)
292
327
  → getStagedFiles() → filterFiles() by preset extensions + size
293
328
  → buildFilesData() → runAnalysis() (via analysis-engine.js)
294
329
  → displayResults() → show quality gate status
295
- if blocking issues (critical/blocker):
296
- generates claude_resolution_prompt.md exit 1 (block)
297
- if non-blocking or no issues: exit 0 (pass)
330
+ judge evaluates ALL issues (any severity):
331
+ TRUE_ISSUE: auto-fix via search/replace + git add
332
+ FALSE_POSITIVE: dismissed
333
+ → ALL resolved: exit 0 (pass)
334
+ → ANY unresolved: generates resolution prompt → exit 1 (block)
335
+ → judge failure: user warned → exit 1 (block)
336
+ → judge disabled: original quality gate (blocks on critical/blocker only)
298
337
  ```
299
338
 
300
339
  **Note:** For interactive review of non-blocking issues, use `claude-hooks analyze` before committing.
@@ -323,6 +362,21 @@ claude-hooks analyze-diff|create-pr → bin/claude-hooks (router)
323
362
  → create-pr: additionally creates PR via Octokit API
324
363
  ```
325
364
 
365
+ #### PR Analysis (analyze-pr)
366
+
367
+ ```
368
+ claude-hooks analyze-pr <url> → bin/claude-hooks (router)
369
+ → lib/commands/analyze-pr.js
370
+ → parseGitHubPRUrl() → fetchPullRequest() + fetchPullRequestFiles()
371
+ → extractLinearTicketFromTitle() → fetchTicket() (optional enrichment)
372
+ → resolvePreset() (labels → ticket → auto-detect → default)
373
+ → loadPrompt('ANALYZE_PR.md') with preset guidelines + categories
374
+ → executeClaudeWithRetry() → extractJSON() → normalizeCategory()
375
+ → interactive comment workflow (confirm/skip)
376
+ → createPullRequestReview() → inline + general comments
377
+ → recordPRAnalysis() (JSONL statistics)
378
+ ```
379
+
326
380
  ### Config Priority
327
381
 
328
382
  ```
@@ -350,7 +404,6 @@ Preset always wins - tech-stack specific has priority over user preferences.
350
404
  "verifyRemote": true // Verify remote exists (v2.11.0)
351
405
  }
352
406
  },
353
- "subagents": { "batchSize": 2 }
354
407
  }
355
408
  }
356
409
  ```
@@ -359,7 +412,7 @@ Preset always wins - tech-stack specific has priority over user preferences.
359
412
 
360
413
  - **Factory**: `preset-loader.js` - dynamic config per tech-stack
361
414
  - **Template Method**: `prompt-builder.js` - prompts from .md templates
362
- - **Strategy**: `claude-client.js` - sequential vs parallel analysis
415
+ - **Strategy**: `analysis-engine.js` - sequential vs orchestrated analysis
363
416
  - **Adapter**: `git-operations.js` - git commands to JS functions
364
417
  - **Command**: `lib/commands/*.js` - one module per CLI command
365
418
 
@@ -370,6 +423,7 @@ Preset always wins - tech-stack specific has priority over user preferences.
370
423
  | CLI argument parsing | `bin/claude-hooks` |
371
424
  | Install workflow | `lib/commands/install.js` |
372
425
  | PR creation flow | `lib/commands/create-pr.js` |
426
+ | PR analysis from URL | `lib/commands/analyze-pr.js` |
373
427
  | Analysis logic | `lib/hooks/pre-commit.js` |
374
428
  | Message generation | `lib/hooks/prepare-commit-msg.js` |
375
429
  | Prompt templates | `templates/*.md` or `.claude/prompts/*.md` |
@@ -377,6 +431,9 @@ Preset always wins - tech-stack specific has priority over user preferences.
377
431
  | Config defaults | `lib/config.js` |
378
432
  | GitHub integration | `lib/utils/github-api.js` |
379
433
  | Claude CLI calls | `lib/utils/claude-client.js` |
434
+ | Batch orchestration logic | `lib/utils/diff-analysis-orchestrator.js` |
435
+ | Orchestration prompt | `templates/DIFF_ANALYSIS_ORCHESTRATION_PROMPT.md` |
436
+ | Auto-fix judge logic | `lib/utils/judge.js` |
380
437
 
381
438
  ### File Structure
382
439
 
@@ -390,40 +447,60 @@ claude-git-hooks/
390
447
  │ │ ├── install.js # Install command - hooks, templates
391
448
  │ │ ├── hooks.js # Hook management - enable/disable
392
449
  │ │ ├── analyze-diff.js # Diff analysis - PR metadata
450
+ │ │ ├── analyze-pr.js # PR analysis - GitHub PR review
393
451
  │ │ ├── create-pr.js # PR creation - Octokit workflow
394
- │ │ ├── setup-github.js # Token setup - interactive config
452
+ │ │ ├── setup-github.js # Token setup - interactive GitHub config
453
+ │ │ ├── setup-linear.js # Token setup - interactive Linear config
395
454
  │ │ ├── presets.js # Preset commands - list/set
396
455
  │ │ ├── update.js # Self-update - npm latest
397
456
  │ │ ├── migrate-config.js # Migration - legacy to v2.8.0
398
457
  │ │ ├── debug.js # Debug mode - toggle verbose
399
458
  │ │ ├── telemetry-cmd.js # Telemetry - show/clear stats
459
+ │ │ ├── diff-batch-info.js # Batch info - orchestration config
400
460
  │ │ └── help.js # Help display - usage info
401
461
  │ ├── hooks/ # Git hooks - Node.js logic
402
462
  │ │ ├── pre-commit.js # Pre-commit analysis
403
463
  │ │ └── prepare-commit-msg.js # Message generation
404
464
  │ └── utils/ # Reusable modules - shared logic
465
+ │ ├── diff-analysis-orchestrator.js # Intelligent batch orchestration
466
+ │ ├── judge.js # Auto-fix judge (v2.20.0)
467
+ │ └── token-store.js # Token persistence - settings.local.json
405
468
  ├── templates/
406
469
  │ ├── pre-commit # Bash wrapper - invokes Node.js
407
470
  │ ├── prepare-commit-msg # Bash wrapper - invokes Node.js
408
- │ ├── *.md # Prompt templates
471
+ │ ├── DIFF_ANALYSIS_ORCHESTRATION_PROMPT.md # Opus orchestration prompt
472
+ │ ├── *.md # Other prompt templates
409
473
  │ └── presets/ # Preset configurations
410
474
  └── test/unit/ # Jest tests
411
475
  ```
412
476
 
413
- ### Parallel Analysis (3+ files)
477
+ ### Analysis Routing (v2.20.0)
414
478
 
415
- Files split into batches, each batch runs in separate Claude CLI process:
416
- - `batchSize: 1` → Maximum parallelism (1 file per process)
417
- - `batchSize: 2` Balanced (2 files per process)
418
- - Results consolidated automatically
479
+ Two-tier strategy based on file count:
480
+
481
+ | Files | Strategy | Details |
482
+ |-------|----------|---------|
483
+ | 1–2 | Sequential | Single Claude call, full context |
484
+ | 3+ | **Intelligent orchestration** | Opus groups files semantically, assigns model per batch, shared commit context |
485
+
486
+ **Orchestration flow (3+ files):**
487
+ 1. Opus reads a lightweight file overview + detected cross-file dependencies
488
+ 2. Groups related files into semantically coherent batches
489
+ 3. Assigns model per batch: `haiku` (config/docs), `sonnet` (business logic), `opus` (security-critical)
490
+ 4. All batches run in parallel; each receives a shared commit overview header
491
+ 5. Falls back to one-file-per-batch if orchestration fails
492
+
493
+ **Inspect orchestration settings:**
494
+ ```bash
495
+ claude-hooks batch-info # Shows config + per-model avg speed from telemetry
496
+ ```
419
497
 
420
- ### Hardcoded Defaults (v2.8.0)
498
+ ### Hardcoded Defaults (v2.8.0+)
421
499
 
422
500
  - Max file size: 1MB
423
- - Max files per commit: 20
424
- - Parallel analysis: enabled
425
- - Parallel model: haiku
426
- - Parallel batch size: 3
501
+ - Max files per commit: 30
502
+ - Orchestrator threshold: 3 files
503
+ - Orchestrator model: opus (internal, not configurable)
427
504
 
428
505
  ---
429
506
 
package/bin/claude-hooks CHANGED
@@ -93,6 +93,7 @@ async function main() {
93
93
  [
94
94
  'install',
95
95
  'analyze-diff',
96
+ 'analyze-pr',
96
97
  'create-pr',
97
98
  'bump-version',
98
99
  'generate-changelog',