claude-git-hooks 2.21.0 → 2.30.2
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 +148 -6
- package/CLAUDE.md +469 -69
- package/README.md +5 -0
- package/bin/claude-hooks +101 -0
- package/lib/cli-metadata.js +68 -1
- package/lib/commands/analyze-pr.js +19 -24
- package/lib/commands/back-merge.js +740 -0
- package/lib/commands/check-coupling.js +209 -0
- package/lib/commands/close-release.js +485 -0
- package/lib/commands/create-pr.js +62 -3
- package/lib/commands/create-release.js +600 -0
- package/lib/commands/diff-batch-info.js +7 -13
- package/lib/commands/help.js +5 -7
- package/lib/commands/install.js +1 -5
- package/lib/commands/revert-feature.js +436 -0
- package/lib/commands/shadow.js +654 -0
- package/lib/config.js +1 -2
- package/lib/hooks/pre-commit.js +8 -6
- package/lib/utils/authorization.js +429 -0
- package/lib/utils/claude-client.js +14 -7
- package/lib/utils/coupling-detector.js +133 -0
- package/lib/utils/diff-analysis-orchestrator.js +7 -14
- package/lib/utils/git-operations.js +480 -1
- package/lib/utils/github-api.js +182 -0
- package/lib/utils/judge.js +66 -7
- package/lib/utils/linear-connector.js +1 -4
- package/lib/utils/package-info.js +0 -1
- package/lib/utils/token-store.js +5 -3
- package/package.json +69 -69
package/CLAUDE.md
CHANGED
|
@@ -11,7 +11,12 @@
|
|
|
11
11
|
3. **Automatic messages**: Write `git commit -m "auto"` and Claude generates the message in Conventional Commits format with task-id extracted from branch
|
|
12
12
|
4. **PR analysis**: `claude-hooks analyze-diff [branch]` generates title, description, and test plan for PRs
|
|
13
13
|
5. **PR review**: `claude-hooks analyze-pr <url>` analyzes a GitHub PR with preset guidelines, Linear ticket enrichment, and posts review comments
|
|
14
|
-
6. **PR creation**: `claude-hooks create-pr [branch]` creates the PR on GitHub with automatic metadata (reviewers from CODEOWNERS, labels by preset)
|
|
14
|
+
6. **PR creation**: `claude-hooks create-pr [branch]` creates the PR on GitHub with automatic metadata (reviewers from CODEOWNERS, labels by preset, merge strategy auto-detected from branch naming)
|
|
15
|
+
7. **Coupling detection**: `claude-hooks check-coupling` scans open PRs targeting a base branch, computes file overlap, and reports which features are coupled (share modified files) — helps TL make informed decisions before cutting a release
|
|
16
|
+
8. **Shadow management**: `claude-hooks shadow <analyze|reset|sync>` manages 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)
|
|
17
|
+
9. **Release creation**: `claude-hooks create-release <major|minor|patch>` creates a release-candidate branch from develop, bumps version files, commits, pushes, and deploys to shadow — replaces the 8 manual steps executed every Tuesday by the Tech Lead
|
|
18
|
+
10. **Feature revert**: `claude-hooks revert-feature <task-id>` finds a squash-merged feature commit by task ID in the current release-candidate, checks coupling with other RC features, reverts it, pushes, and optionally re-deploys shadow
|
|
19
|
+
11. **Release closure**: `claude-hooks close-release [description]` finalizes the active release-candidate — soft-resets onto main, creates a single clean commit, force-pushes, and creates a PR to main with the merge-commit strategy
|
|
15
20
|
|
|
16
21
|
## Architecture
|
|
17
22
|
|
|
@@ -28,7 +33,7 @@
|
|
|
28
33
|
|
|
29
34
|
**Modular, decoupled, reusable code.** Each component has a single responsibility:
|
|
30
35
|
|
|
31
|
-
- **bin/claude-hooks**: Thin CLI router -
|
|
36
|
+
- **bin/claude-hooks**: Thin CLI router - argument parsing, command dispatch, and authorization guard
|
|
32
37
|
- **lib/commands/**: Command modules - one file per CLI command, self-contained logic
|
|
33
38
|
- **lib/hooks/**: Git hook logic - Node.js implementations invoked by bash wrappers
|
|
34
39
|
- **lib/utils/**: Reusable utilities - shared across commands, no CLI dependencies
|
|
@@ -56,6 +61,11 @@ claude-git-hooks/
|
|
|
56
61
|
│ │ ├── hooks.js # Hook management - enable, disable, status, uninstall
|
|
57
62
|
│ │ ├── analyze-diff.js # Diff analysis - generate PR metadata from git diff
|
|
58
63
|
│ │ ├── analyze-pr.js # PR analysis - analyze GitHub PR with team guidelines
|
|
64
|
+
│ │ ├── check-coupling.js # Coupling detection - detect coupled PRs before release (v2.23.0)
|
|
65
|
+
│ │ ├── shadow.js # Shadow management - analyze/reset/sync shadow branch lifecycle (v2.24.0)
|
|
66
|
+
│ │ ├── create-release.js # Release creation - RC branch from develop, version bump, shadow deploy (v2.27.0)
|
|
67
|
+
│ │ ├── revert-feature.js # Feature revert - find by task-id, coupling check, git revert, push, shadow (v2.28.0)
|
|
68
|
+
│ │ ├── close-release.js # Release closure - soft-reset, single commit, force-push, PR to main (v2.29.0)
|
|
59
69
|
│ │ ├── create-pr.js # PR creation - full Octokit workflow
|
|
60
70
|
│ │ ├── setup-github.js # Token setup - interactive GitHub configuration
|
|
61
71
|
│ │ ├── setup-linear.js # Token setup - interactive Linear configuration
|
|
@@ -76,15 +86,18 @@ claude-git-hooks/
|
|
|
76
86
|
│ ├── diff-analysis-orchestrator.js # Intelligent batch orchestration via Opus (v2.20.0)
|
|
77
87
|
│ ├── claude-client.js # Claude CLI wrapper - spawn, retry, model override
|
|
78
88
|
│ ├── prompt-builder.js # Prompt construction - load templates, replace vars
|
|
79
|
-
│ ├── git-operations.js # Git abstractions - staged files, diff, repo root, push, commit
|
|
89
|
+
│ ├── git-operations.js # Git abstractions - staged files, diff, repo root, push, commit, checkout, merge, reset, force-push, delete-remote-branch, divergence
|
|
80
90
|
│ ├── file-utils.js # File operations - repo-relative paths
|
|
81
91
|
│ ├── logger.js # Logging system - centralized output, debug mode
|
|
82
92
|
│ ├── preset-loader.js # Preset system - load tech-stack configurations
|
|
83
93
|
│ ├── pr-metadata-engine.js # PR metadata generation - branch context, diff reduction, metadata (v2.14.0)
|
|
84
94
|
│ ├── github-api.js # Octokit integration - PR creation, PR analysis, token validation
|
|
85
95
|
│ ├── github-client.js # GitHub helpers - CODEOWNERS parsing, reviewers
|
|
96
|
+
│ ├── authorization.js # Role-based authorization - PROTECTED_COMMANDS, authorizeCommand(), fail-closed (v2.23.0)
|
|
97
|
+
│ ├── authorization.js # Role-based authorization - PROTECTED_COMMANDS, authorizeCommand(), fail-closed (v2.23.0)
|
|
86
98
|
│ ├── token-store.js # Token persistence - centralized settings.local.json read/write
|
|
87
99
|
│ ├── linear-connector.js # Linear API - ticket context fetching with retry
|
|
100
|
+
│ ├── coupling-detector.js # Coupling algorithm - Union-Find transitive grouping (v2.23.0)
|
|
88
101
|
│ ├── pr-statistics.js # PR statistics - write-only JSONL analytics
|
|
89
102
|
│ ├── task-id.js # Task ID extraction - Jira, GitHub, Linear patterns
|
|
90
103
|
│ ├── interactive-ui.js # CLI UI components - previews, prompts, spinners
|
|
@@ -176,27 +189,27 @@ preset config (.claude/presets/{name}/config.json) ← HIGHEST PRIORITY
|
|
|
176
189
|
"showCommits": true, // Show commit preview (v2.11.0)
|
|
177
190
|
"verifyRemote": true // Verify remote exists (v2.11.0)
|
|
178
191
|
}
|
|
179
|
-
}
|
|
192
|
+
}
|
|
180
193
|
}
|
|
181
194
|
}
|
|
182
195
|
```
|
|
183
196
|
|
|
184
197
|
**Hardcoded defaults (v2.8.0+):**
|
|
185
198
|
|
|
186
|
-
| Parameter
|
|
187
|
-
|
|
|
188
|
-
| Max file size
|
|
189
|
-
| Max files per commit
|
|
190
|
-
| Orchestrator threshold
|
|
191
|
-
| Orchestrator model
|
|
192
|
-
| Orchestrator timeout
|
|
193
|
-
| Analysis timeout
|
|
194
|
-
| Commit msg timeout
|
|
195
|
-
| PR metadata timeout
|
|
196
|
-
| Judge model
|
|
197
|
-
| Judge timeout
|
|
198
|
-
| PR analysis model
|
|
199
|
-
| PR analysis timeout
|
|
199
|
+
| Parameter | Value | Notes |
|
|
200
|
+
| ---------------------- | ------- | --------------------------------------------------- |
|
|
201
|
+
| Max file size | 1MB | Files larger are skipped |
|
|
202
|
+
| Max files per commit | 30 | Excess files trigger warning |
|
|
203
|
+
| Orchestrator threshold | 3 files | Commits with ≥3 files use Opus orchestration |
|
|
204
|
+
| Orchestrator model | opus | Internal constant — not user-configurable |
|
|
205
|
+
| Orchestrator timeout | 60s | Lightweight call (file overview only) |
|
|
206
|
+
| Analysis timeout | 300s | Per-batch timeout |
|
|
207
|
+
| Commit msg timeout | 300s | Message generation timeout |
|
|
208
|
+
| PR metadata timeout | 180s | Engine default (reads config) |
|
|
209
|
+
| Judge model | sonnet | Default, configurable via `config.judge.model` |
|
|
210
|
+
| Judge timeout | 120s | Per-judge call timeout |
|
|
211
|
+
| PR analysis model | sonnet | Default, configurable via `config.prAnalysis.model` |
|
|
212
|
+
| PR analysis timeout | 300s | Per-analysis Claude call |
|
|
200
213
|
|
|
201
214
|
**Judge behavior (v2.20.0):**
|
|
202
215
|
|
|
@@ -223,9 +236,9 @@ preset config (.claude/presets/{name}/config.json) ← HIGHEST PRIORITY
|
|
|
223
236
|
|
|
224
237
|
Three-tier strategy based on file count:
|
|
225
238
|
|
|
226
|
-
| Files
|
|
227
|
-
|
|
228
|
-
| 1–2
|
|
239
|
+
| Files | Strategy |
|
|
240
|
+
| ------ | ----------------------------------------------------------------------------------------------------- |
|
|
241
|
+
| 1–2 | Sequential — single Claude call |
|
|
229
242
|
| **3+** | **Intelligent orchestration** — Opus orchestrator, semantic grouping, per-batch model, shared context |
|
|
230
243
|
|
|
231
244
|
**Orchestration flow (3+ files):**
|
|
@@ -254,55 +267,62 @@ consolidateResults()
|
|
|
254
267
|
|
|
255
268
|
**Command Modules (`lib/commands/`):**
|
|
256
269
|
|
|
257
|
-
| Module | Purpose
|
|
258
|
-
| ----------------------- |
|
|
259
|
-
| `helpers.js` | Shared CLI utilities
|
|
260
|
-
| `install.js` | Installation logic
|
|
261
|
-
| `hooks.js` | Hook management
|
|
262
|
-
| `analyze.js` | Interactive code analysis
|
|
263
|
-
| `analyze-diff.js` | Diff analysis
|
|
264
|
-
| `analyze-pr.js` | PR analysis from URL
|
|
265
|
-
| `
|
|
266
|
-
| `
|
|
267
|
-
| `
|
|
268
|
-
| `
|
|
269
|
-
| `
|
|
270
|
-
| `
|
|
271
|
-
| `
|
|
272
|
-
| `
|
|
273
|
-
| `
|
|
274
|
-
| `
|
|
275
|
-
| `
|
|
276
|
-
| `
|
|
270
|
+
| Module | Purpose | Key Exports |
|
|
271
|
+
| ----------------------- | --------------------------- | -------------------------------------------------------------------------------------------------- |
|
|
272
|
+
| `helpers.js` | Shared CLI utilities | `colors`, `error()`, `success()`, `info()`, `checkGitRepo()`, `getGitHooksPath()`, `Entertainment` |
|
|
273
|
+
| `install.js` | Installation logic | `runInstall()`, `extractLegacySettings()` |
|
|
274
|
+
| `hooks.js` | Hook management | `runEnable()`, `runDisable()`, `runStatus()`, `runUninstall()` |
|
|
275
|
+
| `analyze.js` | Interactive code analysis | `runAnalyze()` |
|
|
276
|
+
| `analyze-diff.js` | Diff analysis | `runAnalyzeDiff()` |
|
|
277
|
+
| `analyze-pr.js` | PR analysis from URL | `runAnalyzePr()`, `normalizeCategory()` |
|
|
278
|
+
| `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) |
|
|
283
|
+
| `create-pr.js` | PR creation | `runCreatePr()`, `detectMergeStrategy()` (private) |
|
|
284
|
+
| `bump-version.js` | Version management | `runBumpVersion()` |
|
|
285
|
+
| `generate-changelog.js` | CHANGELOG generation | `runGenerateChangelog()` |
|
|
286
|
+
| `setup-github.js` | Token setup (GitHub) | `runSetupGitHub()` |
|
|
287
|
+
| `setup-linear.js` | Token setup (Linear) | `runSetupLinear()` |
|
|
288
|
+
| `presets.js` | Preset management | `runShowPresets()`, `runSetPreset()`, `runCurrentPreset()` |
|
|
289
|
+
| `update.js` | Self-update | `runUpdate()` |
|
|
290
|
+
| `migrate-config.js` | Config migration | `runMigrateConfig()` |
|
|
291
|
+
| `debug.js` | Debug toggle | `runSetDebug()` |
|
|
292
|
+
| `telemetry-cmd.js` | Telemetry commands | `runShowTelemetry()`, `runClearTelemetry()` |
|
|
293
|
+
| `diff-batch-info.js` | Batch info display | `runDiffBatchInfo()` |
|
|
294
|
+
| `help.js` | Help, AI help, report-issue | `runShowHelp()`, `showStaticHelp()`, `runShowVersion()` |
|
|
277
295
|
|
|
278
296
|
**Utility Modules (`lib/utils/`):**
|
|
279
297
|
|
|
280
|
-
| Module
|
|
281
|
-
|
|
|
282
|
-
| `lib/cli-metadata.js`
|
|
283
|
-
| `lib/config.js`
|
|
284
|
-
| `analysis-engine.js`
|
|
285
|
-
| `diff-analysis-orchestrator.js` | Intelligent batch orchestration | `orchestrateBatches()`, `buildFileOverview()`, `detectDependencies()` (v2.20.0)
|
|
286
|
-
| `claude-client.js`
|
|
287
|
-
| `prompt-builder.js`
|
|
288
|
-
| `git-operations.js`
|
|
289
|
-
| `file-utils.js`
|
|
290
|
-
| `pr-metadata-engine.js`
|
|
291
|
-
| `git-tag-manager.js`
|
|
292
|
-
| `version-manager.js`
|
|
293
|
-
| `changelog-generator.js`
|
|
294
|
-
| `
|
|
295
|
-
| `github-
|
|
296
|
-
| `
|
|
297
|
-
| `
|
|
298
|
-
| `
|
|
299
|
-
| `
|
|
300
|
-
| `
|
|
301
|
-
| `
|
|
302
|
-
| `
|
|
303
|
-
| `
|
|
304
|
-
| `
|
|
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
|
+
| `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()` |
|
|
306
326
|
|
|
307
327
|
### Design Patterns
|
|
308
328
|
|
|
@@ -314,6 +334,8 @@ consolidateResults()
|
|
|
314
334
|
6. **Orchestrator Pattern**: `diff-analysis-orchestrator.js` — Opus decides semantic grouping and model assignment; workers (analyzeCode per batch) execute in parallel
|
|
315
335
|
7. **Adapter Pattern**: `git-operations.js` abstracts git commands into JS functions
|
|
316
336
|
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`
|
|
317
339
|
|
|
318
340
|
### Key Data Flows
|
|
319
341
|
|
|
@@ -390,7 +412,7 @@ claude-hooks analyze-pr https://github.com/owner/repo/pull/123
|
|
|
390
412
|
→ recordPRAnalysis() → .claude/statistics/pr/stats.jsonl
|
|
391
413
|
```
|
|
392
414
|
|
|
393
|
-
**Flow 4: PR creation (with auto-push v2.11.0, engine v2.14.0)**
|
|
415
|
+
**Flow 4: PR creation (with auto-push v2.11.0, engine v2.14.0, merge strategy v2.25.0)**
|
|
394
416
|
|
|
395
417
|
```
|
|
396
418
|
claude-hooks create-pr develop
|
|
@@ -399,8 +421,13 @@ claude-hooks create-pr develop
|
|
|
399
421
|
→ pushes branch to remote (if needed)
|
|
400
422
|
→ reads CODEOWNERS → detects reviewers
|
|
401
423
|
→ reads config → applies label rules per preset
|
|
424
|
+
→ detectMergeStrategy(sourceBranch, targetBranch):
|
|
425
|
+
feature/* → squash | release-fix/* → squash
|
|
426
|
+
release-candidate/* → merge-commit | hotfix/* → merge-commit
|
|
427
|
+
any → main → merge-commit | unknown → user prompted to select
|
|
428
|
+
→ adds merge-strategy:<strategy> label; prepends body reminder for merge-commit
|
|
402
429
|
→ analyzeBranchForPR() (pr-metadata-engine.js) → generates metadata
|
|
403
|
-
→ interactive preview → user confirms
|
|
430
|
+
→ interactive preview + strategy info line → user confirms
|
|
404
431
|
→ Octokit creates PR on GitHub
|
|
405
432
|
```
|
|
406
433
|
|
|
@@ -427,6 +454,114 @@ claude-hooks bump-version patch --interactive
|
|
|
427
454
|
|
|
428
455
|
**Per-file version design**: `VersionFileDescriptor` gains an optional `targetVersion` property at runtime, set only by option 'e'. When present, `updateVersionFiles()` writes `targetVersion` instead of the global `newVersion`. The tag and commit message always use the calculated `newVersion`.
|
|
429
456
|
|
|
457
|
+
**Flow 6: Release candidate creation (v2.27.0)**
|
|
458
|
+
|
|
459
|
+
```
|
|
460
|
+
claude-hooks create-release minor
|
|
461
|
+
→ parseArguments() → bumpType, noShadow, dryRun, skipPush, updateChangelog
|
|
462
|
+
→ validatePreconditions():
|
|
463
|
+
checkGitRepo()
|
|
464
|
+
isWorkingDirectoryClean() → abort if dirty
|
|
465
|
+
getCurrentBranch() === 'develop' → abort if not on develop
|
|
466
|
+
fetchRemote() → warn on failure, continue
|
|
467
|
+
getDivergence('develop','origin/develop') → behind>0 → abort + git pull advice
|
|
468
|
+
getDivergence('origin/develop','origin/main') → behind>0 → abort + back-merge advice
|
|
469
|
+
getRemoteBranches().filter('release-candidate/*') → any found → abort + close-release advice
|
|
470
|
+
verifyRemoteExists()
|
|
471
|
+
→ discoverVersionFiles()
|
|
472
|
+
mismatch → abort with table + fix steps (non-interactive, cannot auto-resolve)
|
|
473
|
+
→ incrementVersion(currentVersion, bumpType) [no suffix in branch name]
|
|
474
|
+
→ rcBranch = 'release-candidate/V{nextVersion}'
|
|
475
|
+
→ [--dry-run] → preview table → return
|
|
476
|
+
→ promptConfirmation()
|
|
477
|
+
→ checkoutBranch(rcBranch, { create: true, startPoint: 'develop' })
|
|
478
|
+
→ updateVersionFiles()
|
|
479
|
+
→ [--update-changelog] → generateChangelogEntry() + updateChangelogFile()
|
|
480
|
+
→ stageFiles() + createCommit('chore(version): bump to {nextVersion}', { noVerify: true })
|
|
481
|
+
→ tagExists()? → warn + skip : createTag()
|
|
482
|
+
→ [unless --skip-push] pushBranch(rcBranch, { setUpstream: true })
|
|
483
|
+
→ [unless --no-shadow and not --skip-push] runShadow(['sync', rcBranch])
|
|
484
|
+
shadow error → warn, don't abort
|
|
485
|
+
→ checkoutBranch(rcBranch) [safety: ensure we land on RC after shadow sync]
|
|
486
|
+
→ display summary (branch, version, tag, push status, shadow status)
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
**create-release design decisions:**
|
|
490
|
+
- Mismatch aborts non-interactively (automation context — ambiguity must be fixed by human)
|
|
491
|
+
- Tag creation mirrors `bump-version`: created on RC branch; if tag already exists → warn + skip (no interactive prompt)
|
|
492
|
+
- Shadow sync delegates to `runShadow(['sync', rcBranch])` (public API, reuses conflict-resolution logic from #93)
|
|
493
|
+
- `--skip-push` implies no shadow (cannot sync unpushed branch)
|
|
494
|
+
- Branch naming: `release-candidate/V{semver}` — capital V per team convention, no suffix in branch name
|
|
495
|
+
|
|
496
|
+
**Flow 7: Feature revert in release-candidate (v2.28.0)**
|
|
497
|
+
|
|
498
|
+
```
|
|
499
|
+
claude-hooks revert-feature AUT-3179
|
|
500
|
+
→ parseArgs() → taskId, updateShadow, dryRun
|
|
501
|
+
→ getCurrentBranch() — must start with 'release-candidate/'
|
|
502
|
+
→ isWorkingDirectoryClean() → abort if dirty
|
|
503
|
+
→ git log --grep="AUT-3179" --fixed-strings -i origin/main..HEAD
|
|
504
|
+
0 matches → abort
|
|
505
|
+
1 match → show commit details (hash, message, author, date, files)
|
|
506
|
+
2+ matches → promptMenu() → user selects one
|
|
507
|
+
→ getCommitFiles(targetHash) → target file set
|
|
508
|
+
→ _checkCoupling(): for each other RC commit (skip target, skip Revert commits):
|
|
509
|
+
getCommitFiles(hash) → intersect with targetFiles → collect { taskId, sharedFiles }
|
|
510
|
+
→ [--dry-run] → preview table → return
|
|
511
|
+
→ _displayCommitDetails() + coupling warnings (informational, before single confirmation)
|
|
512
|
+
→ promptConfirmation('Proceed with revert?', false)
|
|
513
|
+
→ git revert --no-edit <hash> → stdio: inherit (shows git output)
|
|
514
|
+
→ git rev-parse HEAD → revertHash
|
|
515
|
+
→ pushBranch(rcBranch)
|
|
516
|
+
→ _appendRevertLog(): append { taskId, originalHash, revertHash, rcBranch, timestamp }
|
|
517
|
+
to .claude/revert-log.json (array, consumed by back-merge #96)
|
|
518
|
+
→ [--update-shadow] runShadow(['sync', rcBranch]) → warn on failure, don't abort
|
|
519
|
+
→ display summary + revert-the-revert reminder:
|
|
520
|
+
git revert <revertHash> # Restores AUT-3179 for next sprint
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
**revert-feature design decisions:**
|
|
524
|
+
- Coupling check is informational only — warnings shown before single confirmation (no second prompt)
|
|
525
|
+
- `Revert "..."` commits are skipped in coupling scan (they intentionally share files)
|
|
526
|
+
- `revert-log.json` schema: `[{ taskId, originalHash, revertHash, rcBranch, timestamp }]` — array to support multiple reverts; consumed by back-merge (#96)
|
|
527
|
+
- `git revert` uses `stdio: 'inherit'` so the user sees git output (including conflict messages)
|
|
528
|
+
- Push failure: revert commit is kept locally; user shown manual `git push` command
|
|
529
|
+
- Shadow sync error: warns but does not abort (non-fatal, same pattern as `create-release`)
|
|
530
|
+
|
|
531
|
+
**Flow 8: Release candidate closure (v2.29.0)**
|
|
532
|
+
|
|
533
|
+
```
|
|
534
|
+
claude-hooks close-release "cashflow + auth"
|
|
535
|
+
→ _parseArgs() → description, autoDescribe, dryRun, noPr
|
|
536
|
+
→ detect RC branch: current branch or getActiveBranch('release-candidate') → offer checkout
|
|
537
|
+
→ _extractVersion(rcBranch) → semver string
|
|
538
|
+
→ isWorkingDirectoryClean() → abort if dirty
|
|
539
|
+
→ fetchRemote() → warn on failure
|
|
540
|
+
→ getDivergence(rc, origin/rc) → behind>0 → abort + git pull advice
|
|
541
|
+
→ _collectFeatureList(): getCommitsBetweenRefs('origin/main', 'HEAD', { format: '%s' })
|
|
542
|
+
→ _resolveDescription():
|
|
543
|
+
CLI arg → use directly
|
|
544
|
+
--auto-describe → executeClaudeWithRetry(haiku, 60s) → 1-line phrase
|
|
545
|
+
default → show list + promptEditField() → TL accepts or overrides
|
|
546
|
+
→ [--dry-run] → preview table → return
|
|
547
|
+
→ promptConfirmation()
|
|
548
|
+
→ resetBranch('origin/main', { mode: 'soft' }) — all RC commits staged
|
|
549
|
+
→ execSync('git commit --no-verify -F -', { input: fullMessage }) — subject + body
|
|
550
|
+
→ forcePush(rcBranch, { lease: true })
|
|
551
|
+
→ [unless --no-pr] validateToken() + createPullRequest(head→main, label: merge-strategy:merge-commit)
|
|
552
|
+
→ display summary with PR URL + merge-commit reminder
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
**close-release design decisions:**
|
|
556
|
+
- `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
|
|
558
|
+
- Description priority: CLI arg > `--auto-describe` (Claude haiku, 60s timeout) > `promptEditField` (shows list, TL edits)
|
|
559
|
+
- Auto-describe fallback: if Claude fails or feature list is empty, falls back to interactive prompt without aborting
|
|
560
|
+
- `close-release` was already in `PROTECTED_COMMANDS` — authorization.js unchanged
|
|
561
|
+
- Force-push failure: exits 1 and shows manual push command (no retry — destructive op)
|
|
562
|
+
- PR creation failure: warns + shows `gh pr create` alternative (non-fatal; commit and push already done)
|
|
563
|
+
- `_extractVersion`, `_collectFeatureList`, `_resolveDescription` are exported for unit testing
|
|
564
|
+
|
|
430
565
|
## Code Conventions
|
|
431
566
|
|
|
432
567
|
### General Style
|
|
@@ -656,6 +791,248 @@ docs: update CLAUDE.md with architecture details
|
|
|
656
791
|
chore(deps): upgrade @octokit/rest to v21
|
|
657
792
|
```
|
|
658
793
|
|
|
794
|
+
## Release Workflow Guide
|
|
795
|
+
|
|
796
|
+
This section provides a practical guide for Tech Leads and Senior developers who use the workflow automation commands. These commands are **protected** — they require `senior` or `tech-lead` role (based on GitHub repo permissions).
|
|
797
|
+
|
|
798
|
+
### Quick Reference — Release Commands
|
|
799
|
+
|
|
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 |
|
|
810
|
+
|
|
811
|
+
### Release Lifecycle — Step by Step
|
|
812
|
+
|
|
813
|
+
The typical weekly release cycle follows this sequence:
|
|
814
|
+
|
|
815
|
+
```
|
|
816
|
+
1. TUESDAY — Prepare release
|
|
817
|
+
claude-hooks check-coupling ← Are any open PRs coupled?
|
|
818
|
+
claude-hooks create-release minor ← Create RC from develop, bump version, shadow deploy
|
|
819
|
+
|
|
820
|
+
2. TUESDAY–THURSDAY — QA cycle
|
|
821
|
+
claude-hooks shadow sync release-candidate ← Re-sync shadow after fixes
|
|
822
|
+
claude-hooks revert-feature AUT-XXXX ← Revert a failing feature if needed
|
|
823
|
+
claude-hooks shadow analyze ← Check shadow divergence
|
|
824
|
+
|
|
825
|
+
3. THURSDAY 12:00 — Close release
|
|
826
|
+
claude-hooks close-release "description" ← Squash RC, create PR to main
|
|
827
|
+
|
|
828
|
+
4. THURSDAY 13:00 — After deploy
|
|
829
|
+
claude-hooks back-merge ← Tag, reset shadow, merge main→develop, cleanup
|
|
830
|
+
```
|
|
831
|
+
|
|
832
|
+
### Command Details
|
|
833
|
+
|
|
834
|
+
#### check-coupling
|
|
835
|
+
|
|
836
|
+
Scans open PRs targeting a base branch and detects which ones share modified files (are "coupled"). Coupled features must ship together or be pulled together — reverting one may break the other.
|
|
837
|
+
|
|
838
|
+
```bash
|
|
839
|
+
claude-hooks check-coupling # PRs targeting develop (default)
|
|
840
|
+
claude-hooks check-coupling --base main # PRs targeting main
|
|
841
|
+
claude-hooks check-coupling --json # Machine-readable output for CI
|
|
842
|
+
```
|
|
843
|
+
|
|
844
|
+
| Flag | Effect |
|
|
845
|
+
|---|---|
|
|
846
|
+
| `--base <branch>` | Base branch to scan PRs against (default: `develop`) |
|
|
847
|
+
| `--json` | Output structured JSON with `coupledGroups`, `independentPRNumbers`, `warnings` |
|
|
848
|
+
|
|
849
|
+
**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
|
+
|
|
851
|
+
---
|
|
852
|
+
|
|
853
|
+
#### create-release
|
|
854
|
+
|
|
855
|
+
Creates a release-candidate branch from `develop`, bumps version files (package.json, pom.xml, etc.), commits, pushes, and deploys to shadow. Replaces 8 manual steps.
|
|
856
|
+
|
|
857
|
+
```bash
|
|
858
|
+
claude-hooks create-release minor # Standard release (most common)
|
|
859
|
+
claude-hooks create-release patch # Hotfix-style bump
|
|
860
|
+
claude-hooks create-release major # Breaking change release
|
|
861
|
+
```
|
|
862
|
+
|
|
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 |
|
|
869
|
+
|
|
870
|
+
**Preconditions** (all checked automatically):
|
|
871
|
+
- Must be on `develop` branch
|
|
872
|
+
- Working directory must be clean
|
|
873
|
+
- `develop` must be up-to-date with remote
|
|
874
|
+
- `develop` must not be behind `main` (run `back-merge` first if so)
|
|
875
|
+
- No existing `release-candidate/*` branch on remote (run `close-release` first)
|
|
876
|
+
|
|
877
|
+
**Branch naming**: `release-candidate/V{version}` (capital V, e.g., `release-candidate/V2.31.0`).
|
|
878
|
+
|
|
879
|
+
---
|
|
880
|
+
|
|
881
|
+
#### shadow
|
|
882
|
+
|
|
883
|
+
Manages the shadow branch — an ephemeral QA environment with its own pipeline. Three subcommands:
|
|
884
|
+
|
|
885
|
+
**shadow analyze** — Show divergence status:
|
|
886
|
+
```bash
|
|
887
|
+
claude-hooks shadow analyze
|
|
888
|
+
```
|
|
889
|
+
Shows how shadow compares to `main` and the active RC (commits ahead/behind). Use this to check if shadow needs a sync.
|
|
890
|
+
|
|
891
|
+
**shadow reset** — Recreate shadow from main:
|
|
892
|
+
```bash
|
|
893
|
+
claude-hooks shadow reset # Destroys and recreates from main
|
|
894
|
+
claude-hooks shadow reset --dry-run # Preview only
|
|
895
|
+
```
|
|
896
|
+
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
|
+
|
|
898
|
+
**shadow sync** — Merge a source branch into shadow:
|
|
899
|
+
```bash
|
|
900
|
+
claude-hooks shadow sync release-candidate # Auto-detect latest RC
|
|
901
|
+
claude-hooks shadow sync release-candidate/V2.31.0 # Explicit RC version
|
|
902
|
+
claude-hooks shadow sync develop # Test develop in shadow
|
|
903
|
+
claude-hooks shadow sync feature/AUT-XXXX # Test a specific feature
|
|
904
|
+
claude-hooks shadow sync <source> --dry-run # Preview only
|
|
905
|
+
```
|
|
906
|
+
|
|
907
|
+
| Flag | Effect |
|
|
908
|
+
|---|---|
|
|
909
|
+
| `--dry-run` | Preview sync without executing |
|
|
910
|
+
|
|
911
|
+
**Conflict resolution during sync**: version files → accept source; CHANGELOG → keep both (warn TL); other conflicts → abort merge and advise manual resolution.
|
|
912
|
+
|
|
913
|
+
---
|
|
914
|
+
|
|
915
|
+
#### revert-feature
|
|
916
|
+
|
|
917
|
+
Finds a squash-merged feature commit by its task ID in the current release-candidate, checks for coupling with other RC features, and reverts it.
|
|
918
|
+
|
|
919
|
+
```bash
|
|
920
|
+
claude-hooks revert-feature AUT-3179 # Find and revert
|
|
921
|
+
claude-hooks revert-feature AUT-3179 --update-shadow # Also re-deploy shadow
|
|
922
|
+
claude-hooks revert-feature AUT-3179 --dry-run # Preview only
|
|
923
|
+
```
|
|
924
|
+
|
|
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 |
|
|
929
|
+
|
|
930
|
+
**Preconditions**: Must be on a `release-candidate/*` branch. Working directory must be clean.
|
|
931
|
+
|
|
932
|
+
**Search behavior**:
|
|
933
|
+
- 0 matches → abort with "No commits found"
|
|
934
|
+
- 1 match → show details, confirm with user
|
|
935
|
+
- 2+ matches → interactive menu to select which commit
|
|
936
|
+
|
|
937
|
+
**Coupling detection**: Before reverting, checks if other RC commits modify the same files. Shows warnings like `"⚠️ [AUT-3200] also modifies EmailService.java"`. This is informational — you decide whether to proceed.
|
|
938
|
+
|
|
939
|
+
**After revert**: Writes to `.claude/revert-log.json` for `back-merge` follow-up. Shows reminder to revert-the-revert in develop after the release deploys.
|
|
940
|
+
|
|
941
|
+
---
|
|
942
|
+
|
|
943
|
+
#### close-release
|
|
944
|
+
|
|
945
|
+
Finalizes the active release-candidate: squashes all RC commits into a single clean commit via `git reset --soft`, force-pushes, and creates a PR to main.
|
|
946
|
+
|
|
947
|
+
```bash
|
|
948
|
+
claude-hooks close-release # Auto-detect RC, prompt for description
|
|
949
|
+
claude-hooks close-release "cashflow + auth" # Explicit description
|
|
950
|
+
claude-hooks close-release --auto-describe # Claude generates 1-line summary
|
|
951
|
+
claude-hooks close-release --dry-run # Preview only
|
|
952
|
+
claude-hooks close-release --no-pr # Skip PR creation
|
|
953
|
+
```
|
|
954
|
+
|
|
955
|
+
| Flag | Effect |
|
|
956
|
+
|---|---|
|
|
957
|
+
| `--dry-run` | Preview planned actions (reset, commit message, PR) without executing |
|
|
958
|
+
| `--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 |
|
|
960
|
+
|
|
961
|
+
**Description priority**: CLI argument → `--auto-describe` → interactive prompt (shows feature list, TL accepts or edits).
|
|
962
|
+
|
|
963
|
+
**Commit format**:
|
|
964
|
+
```
|
|
965
|
+
Release v2.31.0: cashflow improvements + auth fixes
|
|
966
|
+
|
|
967
|
+
Includes:
|
|
968
|
+
- [AUT-3179] feat(cashflow): use Mailjet templates
|
|
969
|
+
- [AUT-3200] fix(cashflow): handle invalid template ID
|
|
970
|
+
```
|
|
971
|
+
|
|
972
|
+
**PR creation**: Labels with `merge-strategy:merge-commit` and adds body reminder. This PR **must** be merged with merge-commit (not squash) to preserve history for back-merge.
|
|
973
|
+
|
|
974
|
+
---
|
|
975
|
+
|
|
976
|
+
#### back-merge
|
|
977
|
+
|
|
978
|
+
Post-deploy synchronization: tags the release on main, resets shadow, merges main into develop (with auto-conflict resolution), and cleans up the RC branch.
|
|
979
|
+
|
|
980
|
+
```bash
|
|
981
|
+
claude-hooks back-merge # Full post-deploy (main → develop)
|
|
982
|
+
claude-hooks back-merge --from main --into develop # Explicit source/destination
|
|
983
|
+
claude-hooks back-merge --skip-tag # Already tagged manually
|
|
984
|
+
claude-hooks back-merge --skip-shadow # Skip shadow reset
|
|
985
|
+
claude-hooks back-merge --dry-run # Preview only
|
|
986
|
+
```
|
|
987
|
+
|
|
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 |
|
|
995
|
+
|
|
996
|
+
**Auto-conflict resolution**:
|
|
997
|
+
| Conflict type | Resolution |
|
|
998
|
+
|---|---|
|
|
999
|
+
| Version files (pom.xml, package.json) | Accept source (released version) |
|
|
1000
|
+
| CHANGELOG.md | Keep both — destination on top, source below |
|
|
1001
|
+
| Other | Abort — TL resolves manually |
|
|
1002
|
+
|
|
1003
|
+
**Revert follow-up**: If `.claude/revert-log.json` exists (from `revert-feature`), shows reverted features and offers to revert-the-revert in develop (restores them for next sprint).
|
|
1004
|
+
|
|
1005
|
+
**Branch protection note**: `back-merge` pushes directly to `develop`. If branch protection requires PRs, you must temporarily disable it or have bypass permissions.
|
|
1006
|
+
|
|
1007
|
+
---
|
|
1008
|
+
|
|
1009
|
+
#### create-pr (merge strategy awareness)
|
|
1010
|
+
|
|
1011
|
+
When creating a PR, the merge strategy is auto-detected from branch naming and displayed in the preview:
|
|
1012
|
+
|
|
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 | — |
|
|
1021
|
+
|
|
1022
|
+
For merge-commit PRs, a reminder is added to the PR body: `"> ⚠️ This PR must be merged with **merge commit** (not squash)"`.
|
|
1023
|
+
|
|
1024
|
+
### Authorization
|
|
1025
|
+
|
|
1026
|
+
All workflow commands (except `check-coupling` and `create-pr`) are protected by role-based authorization:
|
|
1027
|
+
|
|
1028
|
+
- **Protected commands**: `create-release`, `close-release`, `back-merge`, `shadow`, `revert-feature`, `bump-version`
|
|
1029
|
+
- **Role hierarchy**: `developer` < `senior` < `tech-lead`
|
|
1030
|
+
- **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)
|
|
1032
|
+
- **Fail-closed**: Any auth error (no token, invalid token, network failure, repo not governed) blocks the command
|
|
1033
|
+
|
|
1034
|
+
If blocked: `"⛔ Command 'create-release' requires role 'senior'. Your role: developer. Contact your Tech Lead."`
|
|
1035
|
+
|
|
659
1036
|
## Useful Commands
|
|
660
1037
|
|
|
661
1038
|
### Development
|
|
@@ -704,6 +1081,29 @@ claude-hooks preset current # View current preset
|
|
|
704
1081
|
claude-hooks analyze-diff [branch] # Analyze diff for PR
|
|
705
1082
|
claude-hooks analyze-pr <pr-url> # Analyze GitHub PR with team guidelines
|
|
706
1083
|
claude-hooks analyze-pr <url> --dry-run # Analyze without posting comments
|
|
1084
|
+
claude-hooks check-coupling # Detect coupled PRs targeting develop
|
|
1085
|
+
claude-hooks check-coupling --base main # Explicit base branch
|
|
1086
|
+
claude-hooks check-coupling --json # Machine-readable JSON output
|
|
1087
|
+
claude-hooks shadow analyze # Show shadow divergence vs main + active RC
|
|
1088
|
+
claude-hooks shadow reset # Destroy shadow and recreate from main
|
|
1089
|
+
claude-hooks shadow reset --dry-run # Preview reset without executing
|
|
1090
|
+
claude-hooks shadow sync release-candidate # Merge latest RC into shadow (auto-detect)
|
|
1091
|
+
claude-hooks shadow sync release-candidate/V2.7.0 # Merge explicit RC into shadow
|
|
1092
|
+
claude-hooks shadow sync develop # Merge develop into shadow
|
|
1093
|
+
claude-hooks shadow sync release-candidate --dry-run # Preview sync without executing
|
|
1094
|
+
claude-hooks create-release minor # Create RC branch, bump, push, shadow
|
|
1095
|
+
claude-hooks create-release minor --no-shadow # Skip shadow deployment
|
|
1096
|
+
claude-hooks create-release minor --dry-run # Preview only
|
|
1097
|
+
claude-hooks create-release minor --skip-push # Local only (skips shadow too)
|
|
1098
|
+
claude-hooks create-release minor --update-changelog # Include CHANGELOG
|
|
1099
|
+
claude-hooks revert-feature AUT-3179 # Find and revert by task ID
|
|
1100
|
+
claude-hooks revert-feature AUT-3179 --update-shadow # Revert and re-deploy shadow
|
|
1101
|
+
claude-hooks revert-feature AUT-3179 --dry-run # Preview only
|
|
1102
|
+
claude-hooks close-release # Auto-detect RC, prompt for description
|
|
1103
|
+
claude-hooks close-release "cashflow + auth" # Explicit description
|
|
1104
|
+
claude-hooks close-release --auto-describe # Claude generates summary
|
|
1105
|
+
claude-hooks close-release --dry-run # Preview only
|
|
1106
|
+
claude-hooks close-release --no-pr # Skip PR creation
|
|
707
1107
|
claude-hooks create-pr [branch] # Create PR on GitHub
|
|
708
1108
|
claude-hooks setup-github # Configure GitHub token
|
|
709
1109
|
claude-hooks setup-linear # Configure Linear token
|