claude-git-hooks 2.11.0 → 2.13.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 +89 -20
- package/README.md +95 -4
- package/bin/claude-hooks +16 -0
- package/lib/commands/analyze.js +217 -0
- package/lib/commands/bump-version.js +467 -0
- package/lib/commands/create-pr.js +104 -0
- package/lib/commands/generate-changelog.js +154 -0
- package/lib/commands/help.js +53 -0
- package/lib/hooks/pre-commit.js +26 -265
- package/lib/utils/analysis-engine.js +469 -0
- package/lib/utils/changelog-generator.js +382 -0
- package/lib/utils/git-operations.js +130 -1
- package/lib/utils/git-tag-manager.js +566 -0
- package/lib/utils/interactive-ui.js +86 -1
- package/lib/utils/resolution-prompt.js +57 -34
- package/lib/utils/version-manager.js +750 -0
- package/package.json +1 -1
- package/templates/GENERATE_CHANGELOG.md +83 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,28 +5,95 @@ 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.13.0] - 2026-02-05
|
|
9
|
+
|
|
10
|
+
### ✨ Added
|
|
11
|
+
- Interactive analysis command `claude-hooks analyze` - review all issues (INFO to BLOCKER) interactively before committing with auto-commit option
|
|
12
|
+
- Shared analysis engine module (`analysis-engine.js`) - centralized file data building, analysis orchestration, and results display for both pre-commit hooks and interactive analysis
|
|
13
|
+
- Support for version files in subdirectories - automatically searches parent directories when version files not found in repo root
|
|
14
|
+
- Auto-commit functionality after interactive analysis - creates commit with auto-generated message when user confirms
|
|
15
|
+
|
|
16
|
+
### 🔧 Changed
|
|
17
|
+
- Improved version detection logic for pom.xml files - enhanced reliability of version extraction in Maven projects
|
|
18
|
+
|
|
19
|
+
### 🐛 Fixed
|
|
20
|
+
- Fixed version search logic for pom.xml files - corrected parsing issues in Maven version detection
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
## [2.12.0] - 2026-02-03
|
|
24
|
+
|
|
25
|
+
### ✨ Added
|
|
26
|
+
|
|
27
|
+
- **Automatic version management with `bump-version` command**
|
|
28
|
+
- Detects project type (Node.js, Maven, or monorepo with both)
|
|
29
|
+
- Increments version following semantic versioning (major/minor/patch)
|
|
30
|
+
- Supports version suffixes (SNAPSHOT, RC, custom)
|
|
31
|
+
- Updates package.json and/or pom.xml automatically
|
|
32
|
+
- Generates CHANGELOG entries using Claude AI analysis of commits
|
|
33
|
+
- Creates annotated Git tags with `v` prefix (v2.7.0, v2.7.0-SNAPSHOT)
|
|
34
|
+
- Automatically pushes tags to remote
|
|
35
|
+
- CLI options: `--suffix`, `--update-changelog`, `--dry-run`, `--no-tag`, `--no-push`
|
|
36
|
+
|
|
37
|
+
- **CHANGELOG generation with Claude integration**
|
|
38
|
+
- Standalone `generate-changelog` command for independent CHANGELOG generation without version bumping
|
|
39
|
+
- Support for manual version specification in CHANGELOG generation via command argument
|
|
40
|
+
- Base branch selection for CHANGELOG comparison via `--base-branch` flag
|
|
41
|
+
- Release marking option via `--release` flag to control [Unreleased] header behavior
|
|
42
|
+
- Analyzes commits since last final version tag
|
|
43
|
+
- Categorizes changes by Conventional Commits types
|
|
44
|
+
- Generates human-readable entries in Keep a Changelog format
|
|
45
|
+
- Sections: Added, Changed, Fixed, Security, Deprecated, Removed
|
|
46
|
+
- Places entries in [Unreleased] for suffixed versions, [X.Y.Z] for final versions
|
|
47
|
+
|
|
48
|
+
- **Version alignment validation in `create-pr`** (#44)
|
|
49
|
+
- Checks consistency across package.json, pom.xml, CHANGELOG.md, and git tags
|
|
50
|
+
- Compares local version vs remote version
|
|
51
|
+
- Shows helpful prompts with fix commands if misalignment detected
|
|
52
|
+
- Allows user to continue or abort PR creation based on validation results
|
|
53
|
+
|
|
54
|
+
- **Unpushed tags detection in `create-pr`** (#44)
|
|
55
|
+
- Detects local tags not pushed to remote
|
|
56
|
+
- Prompts user to push tags before creating PR
|
|
57
|
+
- Prevents version inconsistencies between local and remote
|
|
58
|
+
|
|
59
|
+
- **New utility modules**:
|
|
60
|
+
- `lib/utils/version-manager.js` - Version detection, parsing, incrementing, validation
|
|
61
|
+
- `lib/utils/git-tag-manager.js` - Git tag operations (create, list, compare, push, isSemverTag)
|
|
62
|
+
- `lib/utils/changelog-generator.js` - CHANGELOG generation with Claude
|
|
63
|
+
- `templates/GENERATE_CHANGELOG.md` - Claude prompt for changelog analysis
|
|
64
|
+
|
|
65
|
+
### 🔧 Changed
|
|
66
|
+
|
|
67
|
+
- Improved Windows compatibility by quoting git log format string in changelog-generator.js
|
|
68
|
+
|
|
69
|
+
### 📚 Documentation
|
|
70
|
+
|
|
71
|
+
- Updated help.js with bump-version command documentation and examples
|
|
72
|
+
- Added version workflow examples (development → RC → release)
|
|
73
|
+
- Updated CLAUDE.md with new utility modules and exports
|
|
74
|
+
|
|
8
75
|
## [2.11.0] - 2026-02-03
|
|
9
76
|
|
|
10
77
|
### ✨ Added
|
|
11
78
|
|
|
12
79
|
- **Auto-push functionality in `create-pr` command** - Automatically detects and pushes unpublished branches before creating PR (#59, #34)
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
80
|
+
- Handles 3 scenarios: unpublished branch, unpushed commits, up-to-date branch
|
|
81
|
+
- Interactive confirmation prompt before pushing (configurable)
|
|
82
|
+
- Commit preview showing what will be pushed
|
|
83
|
+
- Diverged branch detection with helpful error message and resolution steps
|
|
84
|
+
- Never uses `git push --force` for security
|
|
18
85
|
|
|
19
86
|
- **New configuration options** under `github.pr`:
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
87
|
+
- `autoPush: true` - Enable/disable auto-push (enabled by default)
|
|
88
|
+
- `pushConfirm: true` - Prompt for confirmation before push
|
|
89
|
+
- `showCommits: true` - Show commit preview before push
|
|
90
|
+
- `verifyRemote: true` - Verify remote exists before push
|
|
24
91
|
|
|
25
92
|
- **New git-operations functions**:
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
93
|
+
- `getRemoteName()` - Get configured remote name (usually 'origin')
|
|
94
|
+
- `verifyRemoteExists()` - Check if remote is configured
|
|
95
|
+
- `getBranchPushStatus()` - Detect branch publish status and unpushed commits
|
|
96
|
+
- `pushBranch()` - Execute git push with upstream tracking
|
|
30
97
|
|
|
31
98
|
### 🔧 Fixed
|
|
32
99
|
|
|
@@ -76,13 +143,13 @@ This release implements a **modular, decoupled, reusable** architecture for bett
|
|
|
76
143
|
|
|
77
144
|
### 🎯 Benefits
|
|
78
145
|
|
|
79
|
-
| Aspect
|
|
80
|
-
|
|
81
|
-
| `bin/claude-hooks` size | 2,277 lines
|
|
82
|
-
| Command modules
|
|
83
|
-
| Testability
|
|
84
|
-
| Finding code
|
|
85
|
-
| Adding commands
|
|
146
|
+
| Aspect | Before | After |
|
|
147
|
+
| ----------------------- | --------------------- | ------------------------- |
|
|
148
|
+
| `bin/claude-hooks` size | 2,277 lines | 111 lines |
|
|
149
|
+
| Command modules | 1 (`setup-github.js`) | 13 files |
|
|
150
|
+
| Testability | Hard (monolithic) | Easy (modular) |
|
|
151
|
+
| Finding code | Search entire file | Match filename to command |
|
|
152
|
+
| Adding commands | Edit large file | Create new module |
|
|
86
153
|
|
|
87
154
|
### 📚 Documentation
|
|
88
155
|
|
|
@@ -94,6 +161,7 @@ This release implements a **modular, decoupled, reusable** architecture for bett
|
|
|
94
161
|
### 🔧 Technical Details
|
|
95
162
|
|
|
96
163
|
**New module structure:**
|
|
164
|
+
|
|
97
165
|
```
|
|
98
166
|
lib/commands/
|
|
99
167
|
├── helpers.js (389 lines) - Shared utilities
|
|
@@ -111,6 +179,7 @@ lib/commands/
|
|
|
111
179
|
```
|
|
112
180
|
|
|
113
181
|
**Key patterns implemented:**
|
|
182
|
+
|
|
114
183
|
- **Command Pattern**: Each CLI command is a self-contained module
|
|
115
184
|
- **Thin Controller**: `bin/claude-hooks` only routes, doesn't implement
|
|
116
185
|
- **Separation of Concerns**: UI helpers in `helpers.js`, business logic in specific modules
|
package/README.md
CHANGED
|
@@ -60,6 +60,33 @@ export GITHUB_TOKEN="ghp_..."
|
|
|
60
60
|
|
|
61
61
|
Create token at https://github.com/settings/tokens with scopes: `repo`, `read:org`
|
|
62
62
|
|
|
63
|
+
### Analyze Code (Interactive Review)
|
|
64
|
+
|
|
65
|
+
Run interactive code analysis before committing:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
# Analyze staged changes (default)
|
|
69
|
+
claude-hooks analyze
|
|
70
|
+
|
|
71
|
+
# Analyze unstaged changes
|
|
72
|
+
claude-hooks analyze --unstaged
|
|
73
|
+
|
|
74
|
+
# Analyze all tracked files
|
|
75
|
+
claude-hooks analyze --all
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**What it does:**
|
|
79
|
+
- Analyzes selected file scope (staged, unstaged, or all)
|
|
80
|
+
- Shows all issues (INFO, MINOR, MAJOR, CRITICAL, BLOCKER)
|
|
81
|
+
- Interactive prompt with options:
|
|
82
|
+
- **Continue**: Creates commit automatically with auto-generated message
|
|
83
|
+
- **Abort**: Generate resolution prompt and fix issues
|
|
84
|
+
- **View**: Show detailed issue list
|
|
85
|
+
- Executes `git commit -m "auto" --no-verify` on confirmation
|
|
86
|
+
- Works outside git hooks (no stdin limitations)
|
|
87
|
+
|
|
88
|
+
**Use case:** Complete analysis-to-commit workflow in one command.
|
|
89
|
+
|
|
63
90
|
### Analyze Diff (without creating PR)
|
|
64
91
|
|
|
65
92
|
```bash
|
|
@@ -67,6 +94,65 @@ claude-hooks analyze-diff develop
|
|
|
67
94
|
# Generates PR metadata without creating
|
|
68
95
|
```
|
|
69
96
|
|
|
97
|
+
### Bump Version
|
|
98
|
+
|
|
99
|
+
Automatic version management with CHANGELOG generation and Git tagging:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
# Bump patch version (1.0.0 → 1.0.1)
|
|
103
|
+
claude-hooks bump-version patch
|
|
104
|
+
|
|
105
|
+
# Bump with suffix
|
|
106
|
+
claude-hooks bump-version minor --suffix SNAPSHOT # → 1.1.0-SNAPSHOT
|
|
107
|
+
|
|
108
|
+
# Bump and generate CHANGELOG
|
|
109
|
+
claude-hooks bump-version major --update-changelog
|
|
110
|
+
|
|
111
|
+
# Preview without applying
|
|
112
|
+
claude-hooks bump-version patch --dry-run
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
**What it does:**
|
|
116
|
+
- Detects project type (Node.js, Maven, or monorepo with both)
|
|
117
|
+
- Updates `package.json` and/or `pom.xml`
|
|
118
|
+
- Generates CHANGELOG entry with Claude (analyzes commits)
|
|
119
|
+
- Creates annotated Git tag with `v` prefix (e.g., `v2.7.0`)
|
|
120
|
+
- Pushes tag to remote automatically
|
|
121
|
+
|
|
122
|
+
**Version workflow:**
|
|
123
|
+
```
|
|
124
|
+
2.7.0 → 2.8.0-SNAPSHOT # Start development
|
|
125
|
+
2.8.0-SNAPSHOT → 2.8.0-RC # Release candidate
|
|
126
|
+
2.8.0-RC → 2.8.0 # Final release
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
**Integration with create-pr:**
|
|
130
|
+
- Validates version alignment (package.json, pom.xml, CHANGELOG, tags)
|
|
131
|
+
- Detects and prompts to push unpushed tags
|
|
132
|
+
- Warns if local version ≤ remote version
|
|
133
|
+
|
|
134
|
+
### Generate CHANGELOG
|
|
135
|
+
|
|
136
|
+
Standalone CHANGELOG generation (without version bump):
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
# Auto-detect version from package.json/pom.xml
|
|
140
|
+
claude-hooks generate-changelog
|
|
141
|
+
|
|
142
|
+
# Specific version with release marking
|
|
143
|
+
claude-hooks generate-changelog 2.7.0 --release
|
|
144
|
+
|
|
145
|
+
# Compare against different base branch
|
|
146
|
+
claude-hooks generate-changelog --base-branch develop
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
**What it does:**
|
|
150
|
+
- Analyzes commits since last tag using Claude
|
|
151
|
+
- Categorizes by Conventional Commits types (feat, fix, refactor, etc.)
|
|
152
|
+
- Generates Keep a Changelog format entries
|
|
153
|
+
- Updates CHANGELOG.md automatically
|
|
154
|
+
- Useful when `bump-version --update-changelog` fails
|
|
155
|
+
|
|
70
156
|
### Disable/Enable Hooks
|
|
71
157
|
|
|
72
158
|
```bash
|
|
@@ -164,6 +250,7 @@ claude-hooks --help # Full command reference
|
|
|
164
250
|
|
|
165
251
|
| Module | Purpose | Key Exports |
|
|
166
252
|
|--------|---------|-------------|
|
|
253
|
+
| `analysis-engine.js` | **Shared analysis logic** - file data, orchestration, results (v2.13.0) | `buildFilesData()`, `runAnalysis()`, `consolidateResults()`, `displayResults()` |
|
|
167
254
|
| `claude-client.js` | **Claude CLI wrapper** - spawn, retry, parallel execution | `analyzeCode()`, `analyzeCodeParallel()`, `executeClaudeWithRetry()` |
|
|
168
255
|
| `prompt-builder.js` | **Prompt construction** - load templates, replace variables | `buildAnalysisPrompt()`, `loadPrompt()` |
|
|
169
256
|
| `git-operations.js` | **Git abstractions** - staged files, diff, repo root | `getStagedFiles()`, `getDiff()`, `getRepoRoot()` |
|
|
@@ -183,12 +270,16 @@ claude-hooks --help # Full command reference
|
|
|
183
270
|
```
|
|
184
271
|
git commit → templates/pre-commit (bash wrapper)
|
|
185
272
|
→ lib/hooks/pre-commit.js
|
|
186
|
-
→ getStagedFiles() →
|
|
187
|
-
→
|
|
188
|
-
→
|
|
189
|
-
→ if
|
|
273
|
+
→ getStagedFiles() → filterFiles() by preset extensions + size
|
|
274
|
+
→ buildFilesData() → runAnalysis() (via analysis-engine.js)
|
|
275
|
+
→ displayResults() → show quality gate status
|
|
276
|
+
→ if blocking issues (critical/blocker):
|
|
277
|
+
generates claude_resolution_prompt.md → exit 1 (block)
|
|
278
|
+
→ if non-blocking or no issues: exit 0 (pass)
|
|
190
279
|
```
|
|
191
280
|
|
|
281
|
+
**Note:** For interactive review of non-blocking issues, use `claude-hooks analyze` before committing.
|
|
282
|
+
|
|
192
283
|
#### Commit Message Generation
|
|
193
284
|
|
|
194
285
|
```
|
package/bin/claude-hooks
CHANGED
|
@@ -13,6 +13,7 @@ import { error } from '../lib/commands/helpers.js';
|
|
|
13
13
|
// Import commands
|
|
14
14
|
import { runInstall } from '../lib/commands/install.js';
|
|
15
15
|
import { runEnable, runDisable, runStatus, runUninstall } from '../lib/commands/hooks.js';
|
|
16
|
+
import { runAnalyze } from '../lib/commands/analyze.js';
|
|
16
17
|
import { runAnalyzeDiff } from '../lib/commands/analyze-diff.js';
|
|
17
18
|
import { runCreatePr } from '../lib/commands/create-pr.js';
|
|
18
19
|
import { runSetupGitHub } from '../lib/commands/setup-github.js';
|
|
@@ -22,6 +23,8 @@ import { runMigrateConfig } from '../lib/commands/migrate-config.js';
|
|
|
22
23
|
import { runSetDebug } from '../lib/commands/debug.js';
|
|
23
24
|
import { runShowTelemetry, runClearTelemetry } from '../lib/commands/telemetry-cmd.js';
|
|
24
25
|
import { runShowHelp, runShowVersion } from '../lib/commands/help.js';
|
|
26
|
+
import { runBumpVersion } from '../lib/commands/bump-version.js';
|
|
27
|
+
import { runGenerateChangelog } from '../lib/commands/generate-changelog.js';
|
|
25
28
|
|
|
26
29
|
/**
|
|
27
30
|
* Main CLI router
|
|
@@ -49,6 +52,13 @@ async function main() {
|
|
|
49
52
|
case 'status':
|
|
50
53
|
runStatus();
|
|
51
54
|
break;
|
|
55
|
+
case 'analyze':
|
|
56
|
+
await runAnalyze({
|
|
57
|
+
staged: !args.includes('--unstaged') && !args.includes('--all'),
|
|
58
|
+
unstaged: args.includes('--unstaged'),
|
|
59
|
+
all: args.includes('--all')
|
|
60
|
+
});
|
|
61
|
+
break;
|
|
52
62
|
case 'analyze-diff':
|
|
53
63
|
await runAnalyzeDiff(args.slice(1));
|
|
54
64
|
break;
|
|
@@ -75,6 +85,12 @@ async function main() {
|
|
|
75
85
|
case 'migrate-config':
|
|
76
86
|
await runMigrateConfig();
|
|
77
87
|
break;
|
|
88
|
+
case 'bump-version':
|
|
89
|
+
await runBumpVersion(args.slice(1));
|
|
90
|
+
break;
|
|
91
|
+
case 'generate-changelog':
|
|
92
|
+
await runGenerateChangelog(args.slice(1));
|
|
93
|
+
break;
|
|
78
94
|
case 'telemetry':
|
|
79
95
|
// Handle subcommands: telemetry show, telemetry clear
|
|
80
96
|
if (args[1] === 'show' || args[1] === undefined) {
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File: analyze.js
|
|
3
|
+
* Purpose: On-demand code analysis command (interactive, runs outside git hooks)
|
|
4
|
+
*
|
|
5
|
+
* Why this exists: Git hooks cannot reliably read stdin for interactive prompts
|
|
6
|
+
* (stdin is redirected from /dev/null). This command provides interactive analysis
|
|
7
|
+
* before committing, allowing developers to review all issues and decide whether
|
|
8
|
+
* to proceed or fix them first.
|
|
9
|
+
*
|
|
10
|
+
* Key features:
|
|
11
|
+
* - Runs outside git hook context (stdin works normally)
|
|
12
|
+
* - Analyzes staged, unstaged, or all tracked files
|
|
13
|
+
* - Interactive confirmation with detailed issue view
|
|
14
|
+
* - Generates resolution prompt on abort
|
|
15
|
+
*
|
|
16
|
+
* Usage:
|
|
17
|
+
* claude-hooks analyze # Analyze staged files (default)
|
|
18
|
+
* claude-hooks analyze --unstaged # Analyze unstaged changes
|
|
19
|
+
* claude-hooks analyze --all # Analyze all tracked files
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import { getStagedFiles, getUnstagedFiles, getAllTrackedFiles, createCommit } from '../utils/git-operations.js';
|
|
23
|
+
import { filterFiles } from '../utils/file-operations.js';
|
|
24
|
+
import {
|
|
25
|
+
buildFilesData,
|
|
26
|
+
runAnalysis,
|
|
27
|
+
hasAnyIssues,
|
|
28
|
+
displayIssueSummary
|
|
29
|
+
} from '../utils/analysis-engine.js';
|
|
30
|
+
import { promptUserConfirmation, promptConfirmation } from '../utils/interactive-ui.js';
|
|
31
|
+
import { generateResolutionPrompt } from '../utils/resolution-prompt.js';
|
|
32
|
+
import { getConfig } from '../config.js';
|
|
33
|
+
import { loadPreset } from '../utils/preset-loader.js';
|
|
34
|
+
import logger from '../utils/logger.js';
|
|
35
|
+
import { error, success, info } from './helpers.js';
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Main analyze command
|
|
39
|
+
* Why: Provides interactive analysis before committing
|
|
40
|
+
*
|
|
41
|
+
* @param {Object} options - Command options
|
|
42
|
+
* @param {boolean} options.staged - Analyze staged files (default: true)
|
|
43
|
+
* @param {boolean} options.unstaged - Analyze unstaged files
|
|
44
|
+
* @param {boolean} options.all - Analyze all tracked files
|
|
45
|
+
*/
|
|
46
|
+
export const runAnalyze = async (options = {}) => {
|
|
47
|
+
const { unstaged = false, all = false } = options;
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
// Load configuration
|
|
51
|
+
const config = await getConfig();
|
|
52
|
+
|
|
53
|
+
// Enable debug mode from config
|
|
54
|
+
if (config.system?.debug) {
|
|
55
|
+
logger.setDebugMode(true);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Load active preset for file extensions
|
|
59
|
+
const presetName = config.preset || 'default';
|
|
60
|
+
const { metadata } = await loadPreset(presetName);
|
|
61
|
+
const allowedExtensions = metadata.fileExtensions;
|
|
62
|
+
|
|
63
|
+
// Determine scope
|
|
64
|
+
let scopeLabel = 'staged changes';
|
|
65
|
+
if (all) {
|
|
66
|
+
scopeLabel = 'all tracked files';
|
|
67
|
+
} else if (unstaged) {
|
|
68
|
+
scopeLabel = 'unstaged changes';
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
info(`Analyzing ${scopeLabel} with '${metadata.displayName}' preset...`);
|
|
72
|
+
|
|
73
|
+
// Get files based on scope
|
|
74
|
+
let files = [];
|
|
75
|
+
if (all) {
|
|
76
|
+
files = getAllTrackedFiles({ extensions: allowedExtensions });
|
|
77
|
+
} else if (unstaged) {
|
|
78
|
+
files = getUnstagedFiles({ extensions: allowedExtensions });
|
|
79
|
+
} else {
|
|
80
|
+
files = getStagedFiles({ extensions: allowedExtensions });
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (files.length === 0) {
|
|
84
|
+
info(`No files to analyze in ${scopeLabel}.`);
|
|
85
|
+
process.exit(0);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
logger.debug('analyze', 'Files found', {
|
|
89
|
+
scope: scopeLabel,
|
|
90
|
+
count: files.length,
|
|
91
|
+
extensions: allowedExtensions
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// Filter files by size
|
|
95
|
+
const filteredFiles = await filterFiles(files, {
|
|
96
|
+
maxSize: config.analysis?.maxFileSize || 1048576,
|
|
97
|
+
extensions: allowedExtensions
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
const validFiles = filteredFiles.filter(f => f.valid);
|
|
101
|
+
const invalidFiles = filteredFiles.filter(f => !f.valid);
|
|
102
|
+
|
|
103
|
+
// Show warnings for skipped files
|
|
104
|
+
if (invalidFiles.length > 0) {
|
|
105
|
+
invalidFiles.forEach(file => {
|
|
106
|
+
logger.warning(`Skipping ${file.path}: ${file.reason}`);
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (validFiles.length === 0) {
|
|
111
|
+
info(`No valid files found to analyze in ${scopeLabel}.`);
|
|
112
|
+
process.exit(0);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
info(`Sending ${validFiles.length} file(s) for analysis...`);
|
|
116
|
+
|
|
117
|
+
// Build file data (diff/content) using shared engine
|
|
118
|
+
const filesData = buildFilesData(validFiles, { staged: !unstaged && !all });
|
|
119
|
+
|
|
120
|
+
if (filesData.length === 0) {
|
|
121
|
+
info('No file data could be extracted.');
|
|
122
|
+
process.exit(0);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Run analysis using shared engine
|
|
126
|
+
const result = await runAnalysis(filesData, config, { hook: 'analyze' });
|
|
127
|
+
|
|
128
|
+
// Check results
|
|
129
|
+
if (!hasAnyIssues(result)) {
|
|
130
|
+
console.log('');
|
|
131
|
+
success('No issues found. Code is ready to commit!');
|
|
132
|
+
console.log('');
|
|
133
|
+
|
|
134
|
+
// Prompt user to commit or cancel
|
|
135
|
+
const shouldCommit = await promptConfirmation('Create commit now?', true);
|
|
136
|
+
|
|
137
|
+
if (shouldCommit) {
|
|
138
|
+
info('Creating commit with auto-generated message...');
|
|
139
|
+
console.log('');
|
|
140
|
+
|
|
141
|
+
const commitResult = createCommit('auto', { noVerify: true });
|
|
142
|
+
|
|
143
|
+
if (commitResult.success) {
|
|
144
|
+
success('Commit created successfully!');
|
|
145
|
+
if (commitResult.output) {
|
|
146
|
+
console.log(commitResult.output);
|
|
147
|
+
}
|
|
148
|
+
console.log('');
|
|
149
|
+
process.exit(0);
|
|
150
|
+
} else {
|
|
151
|
+
error(`Commit failed: ${commitResult.error}`);
|
|
152
|
+
console.log('');
|
|
153
|
+
process.exit(1);
|
|
154
|
+
}
|
|
155
|
+
} else {
|
|
156
|
+
info('Commit cancelled. Staged files remain unchanged.');
|
|
157
|
+
console.log('');
|
|
158
|
+
process.exit(0);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Display summary
|
|
163
|
+
console.log('');
|
|
164
|
+
console.log('Analysis complete:');
|
|
165
|
+
displayIssueSummary(result);
|
|
166
|
+
console.log('');
|
|
167
|
+
|
|
168
|
+
// Interactive confirmation (works outside git hook)
|
|
169
|
+
const userChoice = await promptUserConfirmation(result);
|
|
170
|
+
|
|
171
|
+
if (userChoice === 'abort') {
|
|
172
|
+
// Generate resolution prompt
|
|
173
|
+
await generateResolutionPrompt(result, {
|
|
174
|
+
fileCount: filesData.length
|
|
175
|
+
});
|
|
176
|
+
console.log('');
|
|
177
|
+
success('Resolution prompt generated: claude_resolution_prompt.md');
|
|
178
|
+
info('Fix issues and run `claude-hooks analyze` again.');
|
|
179
|
+
console.log('');
|
|
180
|
+
process.exit(1);
|
|
181
|
+
} else {
|
|
182
|
+
// User chose to continue - execute commit automatically
|
|
183
|
+
console.log('');
|
|
184
|
+
|
|
185
|
+
// Safeguard: verify staged files still exist
|
|
186
|
+
const currentStagedFiles = getStagedFiles({ extensions: allowedExtensions });
|
|
187
|
+
if (currentStagedFiles.length === 0) {
|
|
188
|
+
error('No staged files found. Did you unstage changes?');
|
|
189
|
+
process.exit(1);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
info('Creating commit with auto-generated message...');
|
|
193
|
+
console.log('');
|
|
194
|
+
|
|
195
|
+
// Execute commit with --no-verify (skip hooks - we already analyzed)
|
|
196
|
+
const commitResult = createCommit('auto', { noVerify: true });
|
|
197
|
+
|
|
198
|
+
if (commitResult.success) {
|
|
199
|
+
success('Commit created successfully!');
|
|
200
|
+
if (commitResult.output) {
|
|
201
|
+
console.log(commitResult.output);
|
|
202
|
+
}
|
|
203
|
+
console.log('');
|
|
204
|
+
process.exit(0);
|
|
205
|
+
} else {
|
|
206
|
+
error(`Commit failed: ${commitResult.error}`);
|
|
207
|
+
console.log('');
|
|
208
|
+
process.exit(1);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
} catch (err) {
|
|
213
|
+
logger.error('analyze', 'Analysis failed', err);
|
|
214
|
+
error(`Analysis failed: ${err.message}`);
|
|
215
|
+
process.exit(1);
|
|
216
|
+
}
|
|
217
|
+
};
|