claude-git-hooks 2.30.2 → 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 CHANGED
@@ -5,48 +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
+
8
56
  ## [2.30.2] - 2026-03-18
9
57
 
10
58
  ### 🔧 Changed
59
+
11
60
  - Authorization now uses GitHub's `role_name` field instead of legacy `permission` field for more accurate role mapping
12
61
  - Improved authorization error messages to show the actual GitHub permission that failed to map
13
62
 
14
63
  ### 🐛 Fixed
15
- - Fixed role mapping to use `write` instead of `push` to match GitHub's current API role names
16
64
 
65
+ - Fixed role mapping to use `write` instead of `push` to match GitHub's current API role names
17
66
 
18
67
  ## [2.30.1] - 2026-03-17
19
68
 
20
69
  ### ✨ Added
70
+
21
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
22
72
 
23
73
  ### 🔧 Changed
24
- - Increased timeout for AI help commands from 30s to 60s to improve reliability of claude-hooks help queries and issue reporting
25
74
 
75
+ - Increased timeout for AI help commands from 30s to 60s to improve reliability of claude-hooks help queries and issue reporting
26
76
 
27
77
  ## [2.30.0] - 2026-03-17
28
78
 
29
79
  ### ✨ Added
80
+
30
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
31
82
  - Support for `--auto-describe` flag to generate release description using Claude AI
32
83
  - Support for `--dry-run` flag to preview close-release actions without executing
33
84
  - Support for `--no-pr` flag to skip PR creation during release closure
34
85
  - New `back-merge` command for post-deploy branch synchronization (#105)
35
86
 
36
-
37
87
  ## [2.29.0] - 2026-03-17
38
88
 
39
89
  ### ✨ Added
90
+
40
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
41
92
  - Added automatic conflict resolution for version files during back-merge (accepts source/main version)
42
93
  - Added CHANGELOG conflict handling during back-merge - stages with conflict markers and prompts user to continue or abort
43
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
44
95
  - Added branch protection detection during back-merge push with helpful PR creation advice
45
96
 
46
-
47
97
  ## [2.28.0] - 2026-03-17
48
98
 
49
99
  ### ✨ Added
100
+
50
101
  - New `revert-feature` command to revert squash-merged features by task ID in release-candidate branches (#95)
51
102
  - Coupling detection when reverting features - warns if other RC commits share modified files
52
103
  - Revert log tracking at `.claude/revert-log.json` for back-merge workflows
@@ -55,12 +106,13 @@ y este proyecto adhiere a [Semantic Versioning](https://semver.org/spec/v2.0.0.h
55
106
  - New `getCommitFiles()` utility in git-operations for retrieving files changed in a specific commit
56
107
 
57
108
  ### 🐛 Fixed
58
- - Added debug logging for git log failures in revert-feature command to aid troubleshooting
59
109
 
110
+ - Added debug logging for git log failures in revert-feature command to aid troubleshooting
60
111
 
61
112
  ## [2.27.0] - 2026-03-17
62
113
 
63
114
  ### ✨ Added
115
+
64
116
  - New `create-release` command to automate release-candidate branch creation from develop (#94)
65
117
  - Automatic version file discovery and bump during release creation
66
118
  - Git tag creation with skip logic if tag already exists
@@ -71,23 +123,22 @@ y este proyecto adhiere a [Semantic Versioning](https://semver.org/spec/v2.0.0.h
71
123
  - Support for `--update-changelog` flag to generate CHANGELOG entry during release
72
124
  - Comprehensive precondition validation: clean working directory, develop branch check, remote sync verification, existing RC detection
73
125
 
74
-
75
126
  ## [2.26.0] - 2026-03-16
76
127
 
77
128
  ### ✨ Added
78
- - 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)
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)
79
131
  - Merge strategy labels (`merge-strategy:squash` or `merge-strategy:merge-commit`) automatically added to created PRs
80
132
  - Merge strategy display in PR preview showing detected strategy before creation
81
133
  - Body reminder prepended to PR description for merge-commit PRs warning about required merge method
82
134
  - Interactive merge strategy selection prompt when branch pattern is unknown or ambiguous
83
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)
84
136
 
85
-
86
137
  ## [2.25.0] - 2026-03-16
87
138
 
88
139
  ### ✨ Added
89
- - 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)
90
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)
91
142
 
92
143
  ## [2.24.0] - 2026-03-16
93
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 - CODEOWNERS parsing, reviewers
96
- │ ├── authorization.js # Role-based authorization - PROTECTED_COMMANDS, authorizeCommand(), fail-closed (v2.23.0)
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
- | `authorization.js` | Role-based authorization | `authorizeCommand()`, `requiresAuthorization()`, `getRequiredRole()`, `AuthorizationError`, `PROTECTED_COMMANDS` fail-closed guard for workflow commands (v2.23.0) |
316
- | `token-store.js` | Token persistence | `loadToken()`, `saveToken()`, `hasToken()`, `loadLocalSettings()` |
317
- | `linear-connector.js` | Linear integration | `loadLinearToken()`, `testConnection()`, `fetchTicket()`, `extractLinearTicketFromTitle()`, `parseLinearIdentifier()`, `LinearConnectorError` |
318
- | `pr-statistics.js` | PR statistics | `recordPRAnalysis()` — write-only JSONL at `.claude/statistics/pr/stats.jsonl` |
319
- | `preset-loader.js` | Preset system | `loadPreset()`, `listPresets()` |
320
- | `task-id.js` | Task ID extraction | `getOrPromptTaskId()`, `formatWithTaskId()` |
321
- | `logger.js` | Logging system | `info()`, `warning()`, `error()`, `debug()` |
322
- | `judge.js` | Auto-fix judge | `judgeAndFix()`, `applyFix()` — LLM verdict + search/replace fixes (v2.20.0) |
323
- | `resolution-prompt.js` | Issue resolution | `generateResolutionPrompt()` |
324
- | `interactive-ui.js` | CLI UI components | `showPRPreview()`, `promptConfirmation()`, `promptMenu()`, `promptToggleList()`, `promptEditField()`, `promptUserConfirmation()` |
325
- | `telemetry.js` | Local telemetry | `recordEvent()`, `displayStatistics()` |
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/claude-hooks-permissions/permissions.json`
338
- 10. **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/claude-hooks-permissions/permissions.json`
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
- reads CODEOWNERS detects reviewers
423
- reads configapplies label rules per preset
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
- adds merge-strategy:<strategy> label; prepends body reminder for merge-commit
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 *outside* try/catch blocks so that mock-based tests can observe them; the catch only handles git errors
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 | When to use | What it does |
801
- |---|---|---|
802
- | `check-coupling` | Before cutting a release | Scans open PRs for shared files — reveals which features are coupled |
803
- | `create-release` | Tuesday release prep | Creates RC branch from develop, bumps version, pushes, deploys to shadow |
804
- | `shadow` | Throughout QA cycle | Manages the shadow (QA) branch — analyze status, reset, or sync with RC |
805
- | `revert-feature` | During QA, feature fails | Finds and reverts a feature by task ID in the RC, with coupling warnings |
806
- | `close-release` | QA passed, ready for deploy | Squashes RC into one commit, force-pushes, creates PR to main |
807
- | `back-merge` | After production deploy | Tags release, resets shadow, merges main→develop, cleans up RC branch |
808
- | `create-pr` | Any PR creation | Creates GitHub PR with auto-detected merge strategy and labels |
809
- | `bump-version` | Manual version changes | Bumps version files, commits, tags — used outside the release cycle |
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 | Effect |
845
- |---|---|
846
- | `--base <branch>` | Base branch to scan PRs against (default: `develop`) |
847
- | `--json` | Output structured JSON with `coupledGroups`, `independentPRNumbers`, `warnings` |
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 | Effect |
864
- |---|---|
865
- | `--dry-run` | Preview all planned actions without making changes |
866
- | `--no-shadow` | Skip shadow deployment after push |
867
- | `--skip-push` | Keep everything local (implies no shadow) |
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 | Effect |
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 | Effect |
926
- |---|---|
927
- | `--dry-run` | Show what would be reverted without making changes |
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 | Effect |
956
- |---|---|
957
- | `--dry-run` | Preview planned actions (reset, commit message, PR) without executing |
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` | Perform the reset + commit + force-push but skip GitHub PR creation |
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 | Effect |
989
- |---|---|
990
- | `--dry-run` | Preview all planned actions without executing |
991
- | `--from <branch>` | Source branch (default: `main`) |
992
- | `--into <branch>` | Destination branch (default: `develop`) |
993
- | `--skip-tag` | Skip tag creation (useful if already tagged) |
994
- | `--skip-shadow` | Skip shadow reset step |
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 | Strategy | Label |
1014
- |---|---|---|
1015
- | `feature/*` → `develop` | Squash merge | `merge-strategy:squash` |
1016
- | `release-fix/*` → `release-candidate/*` | Squash merge | `merge-strategy:squash` |
1017
- | `release-candidate/*` → `main` | Merge commit | `merge-strategy:merge-commit` |
1018
- | `hotfix/*` → `main` | Merge commit | `merge-strategy:merge-commit` |
1019
- | Any branch → `main` | Merge commit | `merge-strategy:merge-commit` |
1020
- | Unknown pattern | Warning — user prompted to select | — |
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**: `claude-hooks-permissions/permissions.json` repo (controlled by TL/Senior)
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."`