claude-git-hooks 2.30.1 → 2.32.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 +69 -8
- package/CLAUDE.md +117 -87
- package/README.md +117 -93
- package/bin/claude-hooks +14 -2
- package/lib/commands/close-release.js +7 -7
- package/lib/commands/create-pr.js +34 -21
- package/lib/utils/authorization.js +6 -7
- package/lib/utils/github-api.js +97 -65
- package/lib/utils/github-client.js +5 -105
- package/lib/utils/label-resolver.js +232 -0
- package/lib/utils/remote-config.js +102 -0
- package/lib/utils/reviewer-selector.js +154 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,38 +5,99 @@ 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.32.0] - 2026-03-19
|
|
9
|
+
|
|
10
|
+
### ✨ Added
|
|
11
|
+
- Team-based reviewer selection using GitHub Teams API for Pull Requests (#36)
|
|
12
|
+
- New `reviewer-selector.js` module for intelligent team member resolution with PR author exclusion
|
|
13
|
+
- Support for `teamSlug` configuration in `config.github.pr` (defaults to 'automation')
|
|
14
|
+
- Support for `excludeReviewers` configuration with remote and local config merging
|
|
15
|
+
- New GitHub API methods: `listRepoTeams()` and `listTeamMembers()` for team resolution
|
|
16
|
+
|
|
17
|
+
### 🔧 Changed
|
|
18
|
+
- PR reviewer selection now prioritizes GitHub Teams API over CODEOWNERS file
|
|
19
|
+
- Updated `createPullRequest()` to accept `teamReviewers` parameter for team-based review requests
|
|
20
|
+
- Refactored `github-client.js` to focus on config-based fallback reviewers only
|
|
21
|
+
- Enhanced reviewer exclusion logic to merge remote general, remote repo-specific, and local config sources
|
|
22
|
+
- Updated documentation to reflect team-based reviewer workflow in CLAUDE.md and README files
|
|
23
|
+
|
|
24
|
+
### 🗑️ Removed
|
|
25
|
+
- CODEOWNERS file parsing and resolution logic from reviewer selection workflow
|
|
26
|
+
- Methods `readCodeowners()` and `parseCodeownersReviewers()` from `github-client.js`
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
## [2.31.1] - 2026-03-19
|
|
30
|
+
|
|
31
|
+
### 🔧 Changed
|
|
32
|
+
- Migrated authorization config repository from `claude-hooks-config` to `git-hooks-config` as the definitive source for permissions and labels
|
|
33
|
+
- Centralized existing permissions and labels configuration in the definitive repository
|
|
34
|
+
- Updated documentation in CLAUDE.md to reference the new `git-hooks-config` repository and document team-wide remote config pattern
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
## [2.31.0] - 2026-03-19
|
|
38
|
+
|
|
39
|
+
### ✨ Added
|
|
40
|
+
|
|
41
|
+
- Remote config fetcher (`remote-config.js`) for centralized configuration from `git-hooks-config` repository with in-memory caching and graceful degradation
|
|
42
|
+
- Label resolver (`label-resolver.js`) with 5-rule engine for automatic PR label resolution: preset, size (`size:S/M/L/XL`), quality (`breaking-change`, `security`, `performance`), merge strategy, and default labels
|
|
43
|
+
- Automatic label resolution in `create-pr` command with remote config priority and local fallback support
|
|
44
|
+
- Configurable size thresholds for PR size labels via remote config
|
|
45
|
+
|
|
46
|
+
### 🔧 Changed
|
|
47
|
+
|
|
48
|
+
- Updated `close-release` command to use the new label resolver instead of hardcoded merge strategy label
|
|
49
|
+
- Refactored `create-pr` label handling to use dependency injection pattern for local fallback rules
|
|
50
|
+
- Documentation updates in CLAUDE.md, README.md, and README-NPM.md describing the new label resolution system
|
|
51
|
+
|
|
52
|
+
### 🐛 Fixed
|
|
53
|
+
|
|
54
|
+
- Removed duplicate `authorization.js` entry in CLAUDE.md directory structure (#112)
|
|
55
|
+
|
|
56
|
+
## [2.30.2] - 2026-03-18
|
|
57
|
+
|
|
58
|
+
### 🔧 Changed
|
|
59
|
+
|
|
60
|
+
- Authorization now uses GitHub's `role_name` field instead of legacy `permission` field for more accurate role mapping
|
|
61
|
+
- Improved authorization error messages to show the actual GitHub permission that failed to map
|
|
62
|
+
|
|
63
|
+
### 🐛 Fixed
|
|
64
|
+
|
|
65
|
+
- Fixed role mapping to use `write` instead of `push` to match GitHub's current API role names
|
|
66
|
+
|
|
8
67
|
## [2.30.1] - 2026-03-17
|
|
9
68
|
|
|
10
69
|
### ✨ Added
|
|
70
|
+
|
|
11
71
|
- Comprehensive Release Workflow Guide in CLAUDE.md documenting all workflow automation commands (check-coupling, create-release, shadow, revert-feature, close-release, back-merge) with step-by-step lifecycle, command details, and authorization model
|
|
12
72
|
|
|
13
73
|
### 🔧 Changed
|
|
14
|
-
- Increased timeout for AI help commands from 30s to 60s to improve reliability of claude-hooks help queries and issue reporting
|
|
15
74
|
|
|
75
|
+
- Increased timeout for AI help commands from 30s to 60s to improve reliability of claude-hooks help queries and issue reporting
|
|
16
76
|
|
|
17
77
|
## [2.30.0] - 2026-03-17
|
|
18
78
|
|
|
19
79
|
### ✨ Added
|
|
80
|
+
|
|
20
81
|
- New `close-release` command for release-candidate finalization (#ISSUE-97) — soft-resets RC onto main, creates a single clean commit with feature list, force-pushes with lease, and creates PR to main with merge-commit strategy label
|
|
21
82
|
- Support for `--auto-describe` flag to generate release description using Claude AI
|
|
22
83
|
- Support for `--dry-run` flag to preview close-release actions without executing
|
|
23
84
|
- Support for `--no-pr` flag to skip PR creation during release closure
|
|
24
85
|
- New `back-merge` command for post-deploy branch synchronization (#105)
|
|
25
86
|
|
|
26
|
-
|
|
27
87
|
## [2.29.0] - 2026-03-17
|
|
28
88
|
|
|
29
89
|
### ✨ Added
|
|
90
|
+
|
|
30
91
|
- Added `back-merge` command for post-deploy branch synchronization (#96) - automates the release close workflow: tags release, resets shadow to main, merges main into develop, deletes RC branches, and offers to restore reverted features for the next sprint
|
|
31
92
|
- Added automatic conflict resolution for version files during back-merge (accepts source/main version)
|
|
32
93
|
- Added CHANGELOG conflict handling during back-merge - stages with conflict markers and prompts user to continue or abort
|
|
33
94
|
- Added revert follow-up feature that reads revert-log.json and offers to apply revert-the-revert for features removed from the closed RC
|
|
34
95
|
- Added branch protection detection during back-merge push with helpful PR creation advice
|
|
35
96
|
|
|
36
|
-
|
|
37
97
|
## [2.28.0] - 2026-03-17
|
|
38
98
|
|
|
39
99
|
### ✨ Added
|
|
100
|
+
|
|
40
101
|
- New `revert-feature` command to revert squash-merged features by task ID in release-candidate branches (#95)
|
|
41
102
|
- Coupling detection when reverting features - warns if other RC commits share modified files
|
|
42
103
|
- Revert log tracking at `.claude/revert-log.json` for back-merge workflows
|
|
@@ -45,12 +106,13 @@ y este proyecto adhiere a [Semantic Versioning](https://semver.org/spec/v2.0.0.h
|
|
|
45
106
|
- New `getCommitFiles()` utility in git-operations for retrieving files changed in a specific commit
|
|
46
107
|
|
|
47
108
|
### 🐛 Fixed
|
|
48
|
-
- Added debug logging for git log failures in revert-feature command to aid troubleshooting
|
|
49
109
|
|
|
110
|
+
- Added debug logging for git log failures in revert-feature command to aid troubleshooting
|
|
50
111
|
|
|
51
112
|
## [2.27.0] - 2026-03-17
|
|
52
113
|
|
|
53
114
|
### ✨ Added
|
|
115
|
+
|
|
54
116
|
- New `create-release` command to automate release-candidate branch creation from develop (#94)
|
|
55
117
|
- Automatic version file discovery and bump during release creation
|
|
56
118
|
- Git tag creation with skip logic if tag already exists
|
|
@@ -61,23 +123,22 @@ y este proyecto adhiere a [Semantic Versioning](https://semver.org/spec/v2.0.0.h
|
|
|
61
123
|
- Support for `--update-changelog` flag to generate CHANGELOG entry during release
|
|
62
124
|
- Comprehensive precondition validation: clean working directory, develop branch check, remote sync verification, existing RC detection
|
|
63
125
|
|
|
64
|
-
|
|
65
126
|
## [2.26.0] - 2026-03-16
|
|
66
127
|
|
|
67
128
|
### ✨ Added
|
|
68
|
-
|
|
129
|
+
|
|
130
|
+
- Merge strategy auto-detection in `create-pr` command - automatically detects required merge strategy (squash vs merge commit) from branch naming conventions (feature/_ → squash, release-candidate/_ → merge-commit, hotfix/\* → merge-commit, any → main → merge-commit)
|
|
69
131
|
- Merge strategy labels (`merge-strategy:squash` or `merge-strategy:merge-commit`) automatically added to created PRs
|
|
70
132
|
- Merge strategy display in PR preview showing detected strategy before creation
|
|
71
133
|
- Body reminder prepended to PR description for merge-commit PRs warning about required merge method
|
|
72
134
|
- Interactive merge strategy selection prompt when branch pattern is unknown or ambiguous
|
|
73
135
|
- Shadow branch lifecycle management command (`claude-hooks shadow <analyze|reset|sync>`) for managing shadow branches - analyze divergence vs main and active RC, reset shadow to clean copy of main, or sync shadow with source branch (#101)
|
|
74
136
|
|
|
75
|
-
|
|
76
137
|
## [2.25.0] - 2026-03-16
|
|
77
138
|
|
|
78
139
|
### ✨ Added
|
|
79
|
-
- New `shadow` command to manage the shadow branch lifecycle — analyze divergence vs main and active RC, reset shadow to a clean copy of main, or sync shadow with a source branch (RC, develop, feature)
|
|
80
140
|
|
|
141
|
+
- New `shadow` command to manage the shadow branch lifecycle — analyze divergence vs main and active RC, reset shadow to a clean copy of main, or sync shadow with a source branch (RC, develop, feature)
|
|
81
142
|
|
|
82
143
|
## [2.24.0] - 2026-03-16
|
|
83
144
|
|
package/CLAUDE.md
CHANGED
|
@@ -91,10 +91,12 @@ claude-git-hooks/
|
|
|
91
91
|
│ ├── logger.js # Logging system - centralized output, debug mode
|
|
92
92
|
│ ├── preset-loader.js # Preset system - load tech-stack configurations
|
|
93
93
|
│ ├── pr-metadata-engine.js # PR metadata generation - branch context, diff reduction, metadata (v2.14.0)
|
|
94
|
-
│ ├── github-api.js # Octokit integration - PR creation, PR analysis, token validation
|
|
95
|
-
│ ├── github-client.js # GitHub helpers -
|
|
96
|
-
│ ├──
|
|
94
|
+
│ ├── github-api.js # Octokit integration - PR creation, PR analysis, token validation, Teams API
|
|
95
|
+
│ ├── github-client.js # GitHub helpers - repo parsing, config-based reviewers (fallback)
|
|
96
|
+
│ ├── reviewer-selector.js # Team-based reviewer selection - resolve team members, exclude author (v2.32.0)
|
|
97
97
|
│ ├── authorization.js # Role-based authorization - PROTECTED_COMMANDS, authorizeCommand(), fail-closed (v2.23.0)
|
|
98
|
+
│ ├── remote-config.js # Remote config fetcher - cached JSON from git-hooks-config repo (v2.31.0)
|
|
99
|
+
│ ├── label-resolver.js # Label resolution - 5-rule engine with remote + local fallback (v2.31.0)
|
|
98
100
|
│ ├── token-store.js # Token persistence - centralized settings.local.json read/write
|
|
99
101
|
│ ├── linear-connector.js # Linear API - ticket context fetching with retry
|
|
100
102
|
│ ├── coupling-detector.js # Coupling algorithm - Union-Find transitive grouping (v2.23.0)
|
|
@@ -173,6 +175,12 @@ preset config (.claude/presets/{name}/config.json) ← HIGHEST PRIORITY
|
|
|
173
175
|
|
|
174
176
|
**Rationale**: User configures general preferences, preset provides tech-stack-specific overrides.
|
|
175
177
|
|
|
178
|
+
**Team-wide remote config** ([`mscope-S-L/git-hooks-config`](https://github.com/mscope-S-L/git-hooks-config)):
|
|
179
|
+
|
|
180
|
+
- `labels.json` — PR label rules (fetched by `remote-config.js`, consumed by `label-resolver.js`)
|
|
181
|
+
- `permissions.json` — role-based authorization (fetched directly by `authorization.js`, fail-closed)
|
|
182
|
+
- Changes take effect immediately across all governed repos — no tool update needed
|
|
183
|
+
|
|
176
184
|
**Config format (v2.8.0):**
|
|
177
185
|
|
|
178
186
|
```json
|
|
@@ -276,10 +284,10 @@ consolidateResults()
|
|
|
276
284
|
| `analyze-diff.js` | Diff analysis | `runAnalyzeDiff()` |
|
|
277
285
|
| `analyze-pr.js` | PR analysis from URL | `runAnalyzePr()`, `normalizeCategory()` |
|
|
278
286
|
| `check-coupling.js` | Coupling detection | `runCheckCoupling()` |
|
|
279
|
-
| `shadow.js` | Shadow branch management | `runShadow()` — routes to analyze/reset/sync subcommands (v2.24.0)
|
|
280
|
-
| `create-release.js` | Release candidate creation | `runCreateRelease()` — RC branch from develop, version bump, push, shadow deploy (v2.27.0)
|
|
281
|
-
| `revert-feature.js` | Feature revert in RC | `runRevertFeature()` — find by task-id, coupling check, revert, push, shadow sync (v2.28.0)
|
|
282
|
-
| `close-release.js` | Release candidate closure | `runCloseRelease()` — soft-reset, single commit, force-push, PR to main (v2.29.0)
|
|
287
|
+
| `shadow.js` | Shadow branch management | `runShadow()` — routes to analyze/reset/sync subcommands (v2.24.0) |
|
|
288
|
+
| `create-release.js` | Release candidate creation | `runCreateRelease()` — RC branch from develop, version bump, push, shadow deploy (v2.27.0) |
|
|
289
|
+
| `revert-feature.js` | Feature revert in RC | `runRevertFeature()` — find by task-id, coupling check, revert, push, shadow sync (v2.28.0) |
|
|
290
|
+
| `close-release.js` | Release candidate closure | `runCloseRelease()` — soft-reset, single commit, force-push, PR to main (v2.29.0) |
|
|
283
291
|
| `create-pr.js` | PR creation | `runCreatePr()`, `detectMergeStrategy()` (private) |
|
|
284
292
|
| `bump-version.js` | Version management | `runBumpVersion()` |
|
|
285
293
|
| `generate-changelog.js` | CHANGELOG generation | `runGenerateChangelog()` |
|
|
@@ -295,34 +303,37 @@ consolidateResults()
|
|
|
295
303
|
|
|
296
304
|
**Utility Modules (`lib/utils/`):**
|
|
297
305
|
|
|
298
|
-
| Module | Purpose | Key Exports
|
|
299
|
-
| ------------------------------- | ------------------------------- |
|
|
300
|
-
| `lib/cli-metadata.js` | Command registry | `commands`, `buildCommandMap()`, `generateCompletionData()`, `PRESET_NAMES`, `HOOK_NAMES`, `BUMP_TYPES`
|
|
301
|
-
| `lib/config.js` | Config system | `getConfig()`
|
|
302
|
-
| `analysis-engine.js` | Shared analysis logic | `buildFileData()`, `buildFilesData()`, `runAnalysis()`, `consolidateResults()`, `hasBlockingIssues()`, `hasAnyIssues()`, `displayResults()`, `displayIssueSummary()` (v2.13.0+)
|
|
303
|
-
| `diff-analysis-orchestrator.js` | Intelligent batch orchestration | `orchestrateBatches()`, `buildFileOverview()`, `detectDependencies()` (v2.20.0)
|
|
304
|
-
| `claude-client.js` | Claude CLI wrapper | `analyzeCode()`, `executeClaudeWithRetry()`, `extractJSON()` — spawn, retry, model override
|
|
305
|
-
| `prompt-builder.js` | Prompt construction | `buildAnalysisPrompt()`, `loadPrompt()` — accepts `commonContext`, `batchRationale`
|
|
306
|
+
| Module | Purpose | Key Exports |
|
|
307
|
+
| ------------------------------- | ------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
308
|
+
| `lib/cli-metadata.js` | Command registry | `commands`, `buildCommandMap()`, `generateCompletionData()`, `PRESET_NAMES`, `HOOK_NAMES`, `BUMP_TYPES` |
|
|
309
|
+
| `lib/config.js` | Config system | `getConfig()` |
|
|
310
|
+
| `analysis-engine.js` | Shared analysis logic | `buildFileData()`, `buildFilesData()`, `runAnalysis()`, `consolidateResults()`, `hasBlockingIssues()`, `hasAnyIssues()`, `displayResults()`, `displayIssueSummary()` (v2.13.0+) |
|
|
311
|
+
| `diff-analysis-orchestrator.js` | Intelligent batch orchestration | `orchestrateBatches()`, `buildFileOverview()`, `detectDependencies()` (v2.20.0) |
|
|
312
|
+
| `claude-client.js` | Claude CLI wrapper | `analyzeCode()`, `executeClaudeWithRetry()`, `extractJSON()` — spawn, retry, model override |
|
|
313
|
+
| `prompt-builder.js` | Prompt construction | `buildAnalysisPrompt()`, `loadPrompt()` — accepts `commonContext`, `batchRationale` |
|
|
306
314
|
| `git-operations.js` | Git abstractions | `getStagedFiles()`, `getUnstagedFiles()`, `getAllTrackedFiles()`, `getDiff()`, `getRepoRoot()`, `getBranchPushStatus()`, `pushBranch()`, `createCommit()`, `fetchRemote()`, `branchExists()`, `getRemoteBranches()`, `resolveBaseBranch()`, `getChangedFilesBetweenRefs()`, `getDiffBetweenRefs()`, `getCommitsBetweenRefs()`, `checkoutBranch()`, `mergeBranch()`, `resetBranch()`, `forcePush()`, `deleteRemoteBranch()`, `getDivergence()`, `readFileFromRef()`, `getLatestTag()`, `isWorkingDirectoryClean()`, `getActiveBranch()`, `getCommitFiles()` |
|
|
307
|
-
| `file-utils.js` | File operations | `ensureDir()`, `ensureOutputDir()`, `writeOutputFile()`, `walkDirectoryTree()`
|
|
308
|
-
| `pr-metadata-engine.js` | PR metadata generation | `getBranchContext()`, `buildDiffPayload()`, `generatePRMetadata()`, `analyzeBranchForPR()` (v2.14.0)
|
|
309
|
-
| `git-tag-manager.js` | Git tag operations | `createTag()`, `pushTags()`, `getLocalTags()`, `getRemoteTags()`, `compareLocalAndRemoteTags()`, `tagExists()` (v2.12.0)
|
|
310
|
-
| `version-manager.js` | Version management | `discoverVersionFiles()`, `getDiscoveryResult()`, `readVersionFromFile()`, `writeVersionToFile()`, `updateVersionFiles()`, `modifySuffix()`, `incrementVersion()`, `parseVersion()`, `validateVersionFormat()`, `compareVersions()`, `validateVersionAlignment()` (v2.15.5)
|
|
311
|
-
| `changelog-generator.js` | CHANGELOG generation | `generateChangelogEntry()`, `updateChangelogFile()`, `getLastFinalVersionTag()`, `getCommitsSinceTag()`, `discoverChangelogFiles()`, `selectChangelogFile()` (v2.12.0)
|
|
312
|
-
| `coupling-detector.js` | Coupling algorithm | `buildFileIndex()`, `getSharedFiles()`, `detectCouplingGroups()` — Union-Find transitive grouping (v2.23.0)
|
|
313
|
-
| `github-api.js` | Octokit integration | `createPullRequest()`, `fetchPullRequest()`, `fetchPullRequestFiles()`, `createPullRequestReview()`, `parseGitHubPRUrl()`, `validateToken()`, `saveGitHubToken()`, `fetchFileContent()`, `fetchDirectoryListing()`, `createIssue()`, `listOpenPullRequests()`, `getAuthenticatedUser()`, `checkOrgMembership()`, `getCollaboratorPermission()`
|
|
314
|
-
| `github-client.js` | GitHub helpers | `getReviewersForFiles()`, `parseGitHubRepo()`
|
|
315
|
-
| `
|
|
316
|
-
| `
|
|
317
|
-
| `
|
|
318
|
-
| `
|
|
319
|
-
| `
|
|
320
|
-
| `
|
|
321
|
-
| `
|
|
322
|
-
| `
|
|
323
|
-
| `
|
|
324
|
-
| `
|
|
325
|
-
| `
|
|
315
|
+
| `file-utils.js` | File operations | `ensureDir()`, `ensureOutputDir()`, `writeOutputFile()`, `walkDirectoryTree()` |
|
|
316
|
+
| `pr-metadata-engine.js` | PR metadata generation | `getBranchContext()`, `buildDiffPayload()`, `generatePRMetadata()`, `analyzeBranchForPR()` (v2.14.0) |
|
|
317
|
+
| `git-tag-manager.js` | Git tag operations | `createTag()`, `pushTags()`, `getLocalTags()`, `getRemoteTags()`, `compareLocalAndRemoteTags()`, `tagExists()` (v2.12.0) |
|
|
318
|
+
| `version-manager.js` | Version management | `discoverVersionFiles()`, `getDiscoveryResult()`, `readVersionFromFile()`, `writeVersionToFile()`, `updateVersionFiles()`, `modifySuffix()`, `incrementVersion()`, `parseVersion()`, `validateVersionFormat()`, `compareVersions()`, `validateVersionAlignment()` (v2.15.5) |
|
|
319
|
+
| `changelog-generator.js` | CHANGELOG generation | `generateChangelogEntry()`, `updateChangelogFile()`, `getLastFinalVersionTag()`, `getCommitsSinceTag()`, `discoverChangelogFiles()`, `selectChangelogFile()` (v2.12.0) |
|
|
320
|
+
| `coupling-detector.js` | Coupling algorithm | `buildFileIndex()`, `getSharedFiles()`, `detectCouplingGroups()` — Union-Find transitive grouping (v2.23.0) |
|
|
321
|
+
| `github-api.js` | Octokit integration | `createPullRequest()`, `fetchPullRequest()`, `fetchPullRequestFiles()`, `createPullRequestReview()`, `parseGitHubPRUrl()`, `validateToken()`, `saveGitHubToken()`, `fetchFileContent()`, `fetchDirectoryListing()`, `createIssue()`, `listOpenPullRequests()`, `listRepoTeams()`, `listTeamMembers()`, `getAuthenticatedUser()`, `checkOrgMembership()`, `getCollaboratorPermission()` |
|
|
322
|
+
| `github-client.js` | GitHub helpers | `getReviewersForFiles()`, `parseGitHubRepo()` — config-based reviewer fallback |
|
|
323
|
+
| `reviewer-selector.js` | Team-based reviewer selection | `selectReviewers()` — resolve team members via GitHub Teams API, exclude PR author, config fallback (v2.32.0) |
|
|
324
|
+
| `authorization.js` | Role-based authorization | `authorizeCommand()`, `requiresAuthorization()`, `getRequiredRole()`, `AuthorizationError`, `PROTECTED_COMMANDS` — fail-closed guard for workflow commands (v2.23.0) |
|
|
325
|
+
| `remote-config.js` | Remote config fetcher | `fetchRemoteConfig(fileName)`, `CONFIG_REPO_OWNER`, `CONFIG_REPO_NAME`, `_clearCache()` — cached JSON from `git-hooks-config` repo, graceful degradation (v2.31.0) |
|
|
326
|
+
| `label-resolver.js` | Label resolution | `resolveLabels(context)` — 5-rule engine: preset, size, quality, strategy, defaults; remote config priority with local fallback (v2.31.0) |
|
|
327
|
+
| `token-store.js` | Token persistence | `loadToken()`, `saveToken()`, `hasToken()`, `loadLocalSettings()` |
|
|
328
|
+
| `linear-connector.js` | Linear integration | `loadLinearToken()`, `testConnection()`, `fetchTicket()`, `extractLinearTicketFromTitle()`, `parseLinearIdentifier()`, `LinearConnectorError` |
|
|
329
|
+
| `pr-statistics.js` | PR statistics | `recordPRAnalysis()` — write-only JSONL at `.claude/statistics/pr/stats.jsonl` |
|
|
330
|
+
| `preset-loader.js` | Preset system | `loadPreset()`, `listPresets()` |
|
|
331
|
+
| `task-id.js` | Task ID extraction | `getOrPromptTaskId()`, `formatWithTaskId()` |
|
|
332
|
+
| `logger.js` | Logging system | `info()`, `warning()`, `error()`, `debug()` |
|
|
333
|
+
| `judge.js` | Auto-fix judge | `judgeAndFix()`, `applyFix()` — LLM verdict + search/replace fixes (v2.20.0) |
|
|
334
|
+
| `resolution-prompt.js` | Issue resolution | `generateResolutionPrompt()` |
|
|
335
|
+
| `interactive-ui.js` | CLI UI components | `showPRPreview()`, `promptConfirmation()`, `promptMenu()`, `promptToggleList()`, `promptEditField()`, `promptUserConfirmation()` |
|
|
336
|
+
| `telemetry.js` | Local telemetry | `recordEvent()`, `displayStatistics()` |
|
|
326
337
|
|
|
327
338
|
### Design Patterns
|
|
328
339
|
|
|
@@ -334,8 +345,8 @@ consolidateResults()
|
|
|
334
345
|
6. **Orchestrator Pattern**: `diff-analysis-orchestrator.js` — Opus decides semantic grouping and model assignment; workers (analyzeCode per batch) execute in parallel
|
|
335
346
|
7. **Adapter Pattern**: `git-operations.js` abstracts git commands into JS functions
|
|
336
347
|
8. **Singleton Pattern**: `config.js` loads configuration once per execution
|
|
337
|
-
9. **Guard Pattern**: `authorization.js` — fail-closed gate in `bin/claude-hooks` before command dispatch; static `PROTECTED_COMMANDS` set avoids API calls for unprotected commands; permissions sourced from `mscope-S-L/
|
|
338
|
-
10. **
|
|
348
|
+
9. **Guard Pattern**: `authorization.js` — fail-closed gate in `bin/claude-hooks` before command dispatch; static `PROTECTED_COMMANDS` set avoids API calls for unprotected commands; permissions sourced from `mscope-S-L/git-hooks-config/permissions.json`
|
|
349
|
+
10. **Remote Config Pattern**: `remote-config.js` — fetches JSON from `mscope-S-L/git-hooks-config`, caches per-process (including nulls), graceful degradation (warn + return null); `label-resolver.js` — callers receive config via dependency injection and decide fallback
|
|
339
350
|
|
|
340
351
|
### Key Data Flows
|
|
341
352
|
|
|
@@ -412,20 +423,28 @@ claude-hooks analyze-pr https://github.com/owner/repo/pull/123
|
|
|
412
423
|
→ recordPRAnalysis() → .claude/statistics/pr/stats.jsonl
|
|
413
424
|
```
|
|
414
425
|
|
|
415
|
-
**Flow 4: PR creation (with auto-push v2.11.0, engine v2.14.0, merge strategy v2.25.0)**
|
|
426
|
+
**Flow 4: PR creation (with auto-push v2.11.0, engine v2.14.0, merge strategy v2.25.0, label resolver v2.31.0, team reviewers v2.32.0)**
|
|
416
427
|
|
|
417
428
|
```
|
|
418
429
|
claude-hooks create-pr develop
|
|
419
430
|
→ checks branch push status (unpublished/unpushed commits)
|
|
420
431
|
→ shows commit preview → prompts for confirmation
|
|
421
432
|
→ pushes branch to remote (if needed)
|
|
422
|
-
→
|
|
423
|
-
|
|
433
|
+
→ selectReviewers({ org, teamSlug, prAuthor, configReviewers }):
|
|
434
|
+
1. listTeamMembers(org, teamSlug) → resolve team (default: 'automation')
|
|
435
|
+
2. filter out prAuthor
|
|
436
|
+
3. if team empty or API fails → fall back to config.github.pr.reviewers
|
|
424
437
|
→ detectMergeStrategy(sourceBranch, targetBranch):
|
|
425
438
|
feature/* → squash | release-fix/* → squash
|
|
426
439
|
release-candidate/* → merge-commit | hotfix/* → merge-commit
|
|
427
440
|
any → main → merge-commit | unknown → user prompted to select
|
|
428
|
-
→
|
|
441
|
+
→ resolveLabels({ preset, fileCount, mergeStrategy, analysisResult, localLabelRules }):
|
|
442
|
+
1. preset labels (remote presetLabels or local fallback)
|
|
443
|
+
2. size labels: size:S (<10) | size:M (10-50) | size:L (50-100) | size:XL (>100)
|
|
444
|
+
3. quality labels: breaking-change, security, performance (from analysisResult)
|
|
445
|
+
4. strategy label: merge-strategy:squash or merge-strategy:merge-commit
|
|
446
|
+
5. default labels (from remote config only, e.g. needs-review)
|
|
447
|
+
→ prepends body reminder for merge-commit
|
|
429
448
|
→ analyzeBranchForPR() (pr-metadata-engine.js) → generates metadata
|
|
430
449
|
→ interactive preview + strategy info line → user confirms
|
|
431
450
|
→ Octokit creates PR on GitHub
|
|
@@ -487,6 +506,7 @@ claude-hooks create-release minor
|
|
|
487
506
|
```
|
|
488
507
|
|
|
489
508
|
**create-release design decisions:**
|
|
509
|
+
|
|
490
510
|
- Mismatch aborts non-interactively (automation context — ambiguity must be fixed by human)
|
|
491
511
|
- Tag creation mirrors `bump-version`: created on RC branch; if tag already exists → warn + skip (no interactive prompt)
|
|
492
512
|
- Shadow sync delegates to `runShadow(['sync', rcBranch])` (public API, reuses conflict-resolution logic from #93)
|
|
@@ -521,6 +541,7 @@ claude-hooks revert-feature AUT-3179
|
|
|
521
541
|
```
|
|
522
542
|
|
|
523
543
|
**revert-feature design decisions:**
|
|
544
|
+
|
|
524
545
|
- Coupling check is informational only — warnings shown before single confirmation (no second prompt)
|
|
525
546
|
- `Revert "..."` commits are skipped in coupling scan (they intentionally share files)
|
|
526
547
|
- `revert-log.json` schema: `[{ taskId, originalHash, revertHash, rcBranch, timestamp }]` — array to support multiple reverts; consumed by back-merge (#96)
|
|
@@ -553,8 +574,9 @@ claude-hooks close-release "cashflow + auth"
|
|
|
553
574
|
```
|
|
554
575
|
|
|
555
576
|
**close-release design decisions:**
|
|
577
|
+
|
|
556
578
|
- `git commit --no-verify -F -` (stdin) is used instead of `createCommit()` to support multi-line body; `execSync` passes the full message via `input` option (no shell injection risk — fixed string)
|
|
557
|
-
- `process.exit()` calls are placed
|
|
579
|
+
- `process.exit()` calls are placed _outside_ try/catch blocks so that mock-based tests can observe them; the catch only handles git errors
|
|
558
580
|
- Description priority: CLI arg > `--auto-describe` (Claude haiku, 60s timeout) > `promptEditField` (shows list, TL edits)
|
|
559
581
|
- Auto-describe fallback: if Claude fails or feature list is empty, falls back to interactive prompt without aborting
|
|
560
582
|
- `close-release` was already in `PROTECTED_COMMANDS` — authorization.js unchanged
|
|
@@ -797,16 +819,16 @@ This section provides a practical guide for Tech Leads and Senior developers who
|
|
|
797
819
|
|
|
798
820
|
### Quick Reference — Release Commands
|
|
799
821
|
|
|
800
|
-
| Command
|
|
801
|
-
|
|
802
|
-
| `check-coupling` | Before cutting a release
|
|
803
|
-
| `create-release` | Tuesday release prep
|
|
804
|
-
| `shadow`
|
|
805
|
-
| `revert-feature` | During QA, feature fails
|
|
806
|
-
| `close-release`
|
|
807
|
-
| `back-merge`
|
|
808
|
-
| `create-pr`
|
|
809
|
-
| `bump-version`
|
|
822
|
+
| Command | When to use | What it does |
|
|
823
|
+
| ---------------- | --------------------------- | ------------------------------------------------------------------------ |
|
|
824
|
+
| `check-coupling` | Before cutting a release | Scans open PRs for shared files — reveals which features are coupled |
|
|
825
|
+
| `create-release` | Tuesday release prep | Creates RC branch from develop, bumps version, pushes, deploys to shadow |
|
|
826
|
+
| `shadow` | Throughout QA cycle | Manages the shadow (QA) branch — analyze status, reset, or sync with RC |
|
|
827
|
+
| `revert-feature` | During QA, feature fails | Finds and reverts a feature by task ID in the RC, with coupling warnings |
|
|
828
|
+
| `close-release` | QA passed, ready for deploy | Squashes RC into one commit, force-pushes, creates PR to main |
|
|
829
|
+
| `back-merge` | After production deploy | Tags release, resets shadow, merges main→develop, cleans up RC branch |
|
|
830
|
+
| `create-pr` | Any PR creation | Creates GitHub PR with auto-detected merge strategy and labels |
|
|
831
|
+
| `bump-version` | Manual version changes | Bumps version files, commits, tags — used outside the release cycle |
|
|
810
832
|
|
|
811
833
|
### Release Lifecycle — Step by Step
|
|
812
834
|
|
|
@@ -841,10 +863,10 @@ claude-hooks check-coupling --base main # PRs targeting main
|
|
|
841
863
|
claude-hooks check-coupling --json # Machine-readable output for CI
|
|
842
864
|
```
|
|
843
865
|
|
|
844
|
-
| Flag
|
|
845
|
-
|
|
846
|
-
| `--base <branch>` | Base branch to scan PRs against (default: `develop`)
|
|
847
|
-
| `--json`
|
|
866
|
+
| Flag | Effect |
|
|
867
|
+
| ----------------- | ------------------------------------------------------------------------------- |
|
|
868
|
+
| `--base <branch>` | Base branch to scan PRs against (default: `develop`) |
|
|
869
|
+
| `--json` | Output structured JSON with `coupledGroups`, `independentPRNumbers`, `warnings` |
|
|
848
870
|
|
|
849
871
|
**Not protected** — any developer can run this. Uses GitHub API to fetch PR file lists. Transitive coupling is detected (if A shares files with B, and B with C, all three are grouped).
|
|
850
872
|
|
|
@@ -860,14 +882,15 @@ claude-hooks create-release patch # Hotfix-style bump
|
|
|
860
882
|
claude-hooks create-release major # Breaking change release
|
|
861
883
|
```
|
|
862
884
|
|
|
863
|
-
| Flag
|
|
864
|
-
|
|
865
|
-
| `--dry-run`
|
|
866
|
-
| `--no-shadow`
|
|
867
|
-
| `--skip-push`
|
|
868
|
-
| `--update-changelog` | Generate and include CHANGELOG entry
|
|
885
|
+
| Flag | Effect |
|
|
886
|
+
| -------------------- | -------------------------------------------------- |
|
|
887
|
+
| `--dry-run` | Preview all planned actions without making changes |
|
|
888
|
+
| `--no-shadow` | Skip shadow deployment after push |
|
|
889
|
+
| `--skip-push` | Keep everything local (implies no shadow) |
|
|
890
|
+
| `--update-changelog` | Generate and include CHANGELOG entry |
|
|
869
891
|
|
|
870
892
|
**Preconditions** (all checked automatically):
|
|
893
|
+
|
|
871
894
|
- Must be on `develop` branch
|
|
872
895
|
- Working directory must be clean
|
|
873
896
|
- `develop` must be up-to-date with remote
|
|
@@ -883,19 +906,24 @@ claude-hooks create-release major # Breaking change release
|
|
|
883
906
|
Manages the shadow branch — an ephemeral QA environment with its own pipeline. Three subcommands:
|
|
884
907
|
|
|
885
908
|
**shadow analyze** — Show divergence status:
|
|
909
|
+
|
|
886
910
|
```bash
|
|
887
911
|
claude-hooks shadow analyze
|
|
888
912
|
```
|
|
913
|
+
|
|
889
914
|
Shows how shadow compares to `main` and the active RC (commits ahead/behind). Use this to check if shadow needs a sync.
|
|
890
915
|
|
|
891
916
|
**shadow reset** — Recreate shadow from main:
|
|
917
|
+
|
|
892
918
|
```bash
|
|
893
919
|
claude-hooks shadow reset # Destroys and recreates from main
|
|
894
920
|
claude-hooks shadow reset --dry-run # Preview only
|
|
895
921
|
```
|
|
922
|
+
|
|
896
923
|
Used at the start/end of a release cycle. Destroys the current shadow branch and creates a fresh copy from main. Prompts for confirmation.
|
|
897
924
|
|
|
898
925
|
**shadow sync** — Merge a source branch into shadow:
|
|
926
|
+
|
|
899
927
|
```bash
|
|
900
928
|
claude-hooks shadow sync release-candidate # Auto-detect latest RC
|
|
901
929
|
claude-hooks shadow sync release-candidate/V2.31.0 # Explicit RC version
|
|
@@ -904,8 +932,8 @@ claude-hooks shadow sync feature/AUT-XXXX # Test a specific feature
|
|
|
904
932
|
claude-hooks shadow sync <source> --dry-run # Preview only
|
|
905
933
|
```
|
|
906
934
|
|
|
907
|
-
| Flag
|
|
908
|
-
|
|
935
|
+
| Flag | Effect |
|
|
936
|
+
| ----------- | ------------------------------ |
|
|
909
937
|
| `--dry-run` | Preview sync without executing |
|
|
910
938
|
|
|
911
939
|
**Conflict resolution during sync**: version files → accept source; CHANGELOG → keep both (warn TL); other conflicts → abort merge and advise manual resolution.
|
|
@@ -922,14 +950,15 @@ claude-hooks revert-feature AUT-3179 --update-shadow # Also re-deploy shadow
|
|
|
922
950
|
claude-hooks revert-feature AUT-3179 --dry-run # Preview only
|
|
923
951
|
```
|
|
924
952
|
|
|
925
|
-
| Flag
|
|
926
|
-
|
|
927
|
-
| `--dry-run`
|
|
928
|
-
| `--update-shadow` | After reverting, sync shadow with the updated RC
|
|
953
|
+
| Flag | Effect |
|
|
954
|
+
| ----------------- | -------------------------------------------------- |
|
|
955
|
+
| `--dry-run` | Show what would be reverted without making changes |
|
|
956
|
+
| `--update-shadow` | After reverting, sync shadow with the updated RC |
|
|
929
957
|
|
|
930
958
|
**Preconditions**: Must be on a `release-candidate/*` branch. Working directory must be clean.
|
|
931
959
|
|
|
932
960
|
**Search behavior**:
|
|
961
|
+
|
|
933
962
|
- 0 matches → abort with "No commits found"
|
|
934
963
|
- 1 match → show details, confirm with user
|
|
935
964
|
- 2+ matches → interactive menu to select which commit
|
|
@@ -952,15 +981,16 @@ claude-hooks close-release --dry-run # Preview only
|
|
|
952
981
|
claude-hooks close-release --no-pr # Skip PR creation
|
|
953
982
|
```
|
|
954
983
|
|
|
955
|
-
| Flag
|
|
956
|
-
|
|
957
|
-
| `--dry-run`
|
|
984
|
+
| Flag | Effect |
|
|
985
|
+
| ----------------- | --------------------------------------------------------------------------- |
|
|
986
|
+
| `--dry-run` | Preview planned actions (reset, commit message, PR) without executing |
|
|
958
987
|
| `--auto-describe` | Use Claude (haiku, 60s timeout) to generate a description from feature list |
|
|
959
|
-
| `--no-pr`
|
|
988
|
+
| `--no-pr` | Perform the reset + commit + force-push but skip GitHub PR creation |
|
|
960
989
|
|
|
961
990
|
**Description priority**: CLI argument → `--auto-describe` → interactive prompt (shows feature list, TL accepts or edits).
|
|
962
991
|
|
|
963
992
|
**Commit format**:
|
|
993
|
+
|
|
964
994
|
```
|
|
965
995
|
Release v2.31.0: cashflow improvements + auth fixes
|
|
966
996
|
|
|
@@ -985,13 +1015,13 @@ claude-hooks back-merge --skip-shadow # Skip shadow reset
|
|
|
985
1015
|
claude-hooks back-merge --dry-run # Preview only
|
|
986
1016
|
```
|
|
987
1017
|
|
|
988
|
-
| Flag
|
|
989
|
-
|
|
990
|
-
| `--dry-run`
|
|
991
|
-
| `--from <branch>` | Source branch (default: `main`)
|
|
992
|
-
| `--into <branch>` | Destination branch (default: `develop`)
|
|
993
|
-
| `--skip-tag`
|
|
994
|
-
| `--skip-shadow`
|
|
1018
|
+
| Flag | Effect |
|
|
1019
|
+
| ----------------- | --------------------------------------------- |
|
|
1020
|
+
| `--dry-run` | Preview all planned actions without executing |
|
|
1021
|
+
| `--from <branch>` | Source branch (default: `main`) |
|
|
1022
|
+
| `--into <branch>` | Destination branch (default: `develop`) |
|
|
1023
|
+
| `--skip-tag` | Skip tag creation (useful if already tagged) |
|
|
1024
|
+
| `--skip-shadow` | Skip shadow reset step |
|
|
995
1025
|
|
|
996
1026
|
**Auto-conflict resolution**:
|
|
997
1027
|
| Conflict type | Resolution |
|
|
@@ -1010,14 +1040,14 @@ claude-hooks back-merge --dry-run # Preview only
|
|
|
1010
1040
|
|
|
1011
1041
|
When creating a PR, the merge strategy is auto-detected from branch naming and displayed in the preview:
|
|
1012
1042
|
|
|
1013
|
-
| PR direction
|
|
1014
|
-
|
|
1015
|
-
| `feature/*` → `develop`
|
|
1016
|
-
| `release-fix/*` → `release-candidate/*` | Squash merge
|
|
1017
|
-
| `release-candidate/*` → `main`
|
|
1018
|
-
| `hotfix/*` → `main`
|
|
1019
|
-
| Any branch → `main`
|
|
1020
|
-
| Unknown pattern
|
|
1043
|
+
| PR direction | Strategy | Label |
|
|
1044
|
+
| --------------------------------------- | --------------------------------- | ----------------------------- |
|
|
1045
|
+
| `feature/*` → `develop` | Squash merge | `merge-strategy:squash` |
|
|
1046
|
+
| `release-fix/*` → `release-candidate/*` | Squash merge | `merge-strategy:squash` |
|
|
1047
|
+
| `release-candidate/*` → `main` | Merge commit | `merge-strategy:merge-commit` |
|
|
1048
|
+
| `hotfix/*` → `main` | Merge commit | `merge-strategy:merge-commit` |
|
|
1049
|
+
| Any branch → `main` | Merge commit | `merge-strategy:merge-commit` |
|
|
1050
|
+
| Unknown pattern | Warning — user prompted to select | — |
|
|
1021
1051
|
|
|
1022
1052
|
For merge-commit PRs, a reminder is added to the PR body: `"> ⚠️ This PR must be merged with **merge commit** (not squash)"`.
|
|
1023
1053
|
|
|
@@ -1028,7 +1058,7 @@ All workflow commands (except `check-coupling` and `create-pr`) are protected by
|
|
|
1028
1058
|
- **Protected commands**: `create-release`, `close-release`, `back-merge`, `shadow`, `revert-feature`, `bump-version`
|
|
1029
1059
|
- **Role hierarchy**: `developer` < `senior` < `tech-lead`
|
|
1030
1060
|
- **Role mapping**: GitHub repo permission `push` → developer, `maintain` → senior, `admin` → tech-lead
|
|
1031
|
-
- **Permissions source**: `
|
|
1061
|
+
- **Permissions source**: `git-hooks-config/permissions.json` repo (controlled by TL/Senior)
|
|
1032
1062
|
- **Fail-closed**: Any auth error (no token, invalid token, network failure, repo not governed) blocks the command
|
|
1033
1063
|
|
|
1034
1064
|
If blocked: `"⛔ Command 'create-release' requires role 'senior'. Your role: developer. Contact your Tech Lead."`
|