@vibe-validate/git 0.17.6 → 0.18.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.
@@ -0,0 +1,289 @@
1
+ /**
2
+ * Branch Cleanup - Core Analysis Functions
3
+ *
4
+ * Git-aware branch cleanup that safely identifies and removes merged branches.
5
+ * This module provides the core analysis functionality for determining which
6
+ * branches are safe to delete automatically and which need manual review.
7
+ *
8
+ * Safety principles:
9
+ * 1. NEVER delete branches with unpushed work
10
+ * 2. Auto-delete only if 100% safe (merged + no unpushed commits)
11
+ * 3. All deletions are recoverable via reflog
12
+ * 4. Never touch protected branches (main/master/develop)
13
+ *
14
+ * @packageDocumentation
15
+ */
16
+ import { type GitHubPullRequest } from './gh-commands.js';
17
+ /**
18
+ * Remote tracking status for a branch
19
+ */
20
+ export type RemoteStatus = 'exists' | 'deleted' | 'never_pushed';
21
+ /**
22
+ * Git metadata about a branch
23
+ */
24
+ export interface BranchGitFacts {
25
+ /** Branch name */
26
+ name: string;
27
+ /** Is branch merged to default branch */
28
+ mergedToMain: boolean;
29
+ /** Remote tracking status */
30
+ remoteStatus: RemoteStatus;
31
+ /** Number of unpushed commits */
32
+ unpushedCommitCount: number;
33
+ /** Last commit date (ISO 8601) */
34
+ lastCommitDate: string;
35
+ /** Last commit author */
36
+ lastCommitAuthor: string;
37
+ /** Days since last activity */
38
+ daysSinceActivity: number;
39
+ }
40
+ /**
41
+ * GitHub metadata about a branch (from PR data)
42
+ */
43
+ export interface BranchGitHubFacts {
44
+ /** Associated PR number */
45
+ prNumber?: number;
46
+ /** PR state (open, closed, merged) */
47
+ prState?: 'open' | 'closed' | 'merged';
48
+ /** Merge method used */
49
+ mergeMethod?: 'merge' | 'squash' | 'rebase';
50
+ /** When PR was merged */
51
+ mergedAt?: string;
52
+ /** Who merged the PR */
53
+ mergedBy?: string;
54
+ }
55
+ /**
56
+ * Assessment and action commands for a branch
57
+ */
58
+ export interface BranchAssessment {
59
+ /** Human-readable assessment */
60
+ summary: string;
61
+ /** Exact command to delete branch */
62
+ deleteCommand: string;
63
+ /** Command to recover branch after deletion */
64
+ recoveryCommand: string;
65
+ }
66
+ /**
67
+ * Complete analysis of a branch
68
+ */
69
+ export interface BranchAnalysis {
70
+ /** Git facts about the branch */
71
+ gitFacts: BranchGitFacts;
72
+ /** GitHub facts (if available) */
73
+ githubFacts?: BranchGitHubFacts;
74
+ /** Assessment and commands */
75
+ assessment: BranchAssessment;
76
+ }
77
+ /**
78
+ * Context about the cleanup operation
79
+ */
80
+ export interface CleanupContext {
81
+ /** Repository name (owner/repo) */
82
+ repository: string;
83
+ /** Remote name (usually 'origin') */
84
+ remote: string;
85
+ /** Default branch name (main/master/develop) */
86
+ defaultBranch: string;
87
+ /** Branch we were on before switching */
88
+ previousBranch?: string;
89
+ /** Current branch after potential switch */
90
+ currentBranch: string;
91
+ /** Did we switch branches during cleanup? */
92
+ switchedBranch: boolean;
93
+ /** Why we switched (if applicable) */
94
+ switchReason?: string;
95
+ }
96
+ /**
97
+ * Detect the repository's default branch
98
+ *
99
+ * Tries multiple methods in order of reliability:
100
+ * 1. Remote HEAD symbolic ref (most reliable)
101
+ * 2. Git config init.defaultBranch
102
+ * 3. Fallback to 'main'
103
+ *
104
+ * @param options - Options for detection
105
+ * @returns Default branch name
106
+ * @throws Error if throwOnError is true and detection fails
107
+ */
108
+ export declare function detectDefaultBranch(options?: {
109
+ throwOnError?: boolean;
110
+ }): string;
111
+ /**
112
+ * Check if a branch is protected (should never be deleted)
113
+ *
114
+ * @param name - Branch name
115
+ * @param defaultBranch - Default branch name
116
+ * @returns true if branch is protected
117
+ */
118
+ export declare function isProtectedBranch(name: string, defaultBranch: string): boolean;
119
+ /**
120
+ * Parse remote tracking status from git branch -vv output
121
+ *
122
+ * @param branchVerbose - Output from git branch -vv
123
+ * @returns Remote status and ref
124
+ */
125
+ export declare function parseRemoteTracking(branchVerbose: string): {
126
+ remoteStatus: RemoteStatus;
127
+ remoteRef: string | null;
128
+ };
129
+ /**
130
+ * Get unpushed commit count for a branch
131
+ *
132
+ * @param branch - Branch name
133
+ * @param remoteRef - Remote ref (e.g., 'origin/feature/test')
134
+ * @returns Number of unpushed commits
135
+ */
136
+ export declare function getUnpushedCommitCount(branch: string, remoteRef: string | null): number;
137
+ /**
138
+ * Gather git facts about a branch
139
+ *
140
+ * @param branch - Branch name
141
+ * @param _defaultBranch - Default branch name (reserved for future use)
142
+ * @param mergedBranches - Set of branch names that are merged to main
143
+ * @returns Git facts about the branch
144
+ */
145
+ export declare function gatherBranchGitFacts(branch: string, _defaultBranch: string, mergedBranches: Set<string>): Promise<BranchGitFacts>;
146
+ /**
147
+ * Determine if a branch is 100% safe to auto-delete
148
+ *
149
+ * A branch is auto-delete safe if:
150
+ * - Merged to main (detected by git)
151
+ * - Zero unpushed commits
152
+ * - Even if deleted, it's recoverable via reflog
153
+ *
154
+ * @param facts - Git facts about the branch
155
+ * @returns true if safe to auto-delete
156
+ */
157
+ export declare function isAutoDeleteSafe(facts: BranchGitFacts): boolean;
158
+ /**
159
+ * Determine if a branch needs manual review before deletion
160
+ *
161
+ * A branch needs review if:
162
+ * - Not merged (could be squash/rebase merged)
163
+ * - Zero unpushed commits (safe from data loss)
164
+ * - Remote deleted OR >30 days old
165
+ * - NOT if has open PR (obviously keep)
166
+ * - NOT if has unpushed work (obviously keep)
167
+ *
168
+ * @param facts - Git facts about the branch
169
+ * @param githubFacts - GitHub facts (used to check PR state)
170
+ * @returns true if needs manual review
171
+ */
172
+ export declare function needsReview(facts: BranchGitFacts, githubFacts?: BranchGitHubFacts): boolean;
173
+ /**
174
+ * Determine if a branch should be shown in output
175
+ *
176
+ * @param analysis - Branch analysis
177
+ * @returns true if should be shown
178
+ */
179
+ export declare function shouldShowBranch(analysis: BranchAnalysis): boolean;
180
+ /**
181
+ * Detect merge method from PR data
182
+ *
183
+ * Analyzes PR metadata to determine how it was merged:
184
+ * - Squash: merge commit exists but PR has multiple commits
185
+ * - Merge: merge commit with multiple parents (true merge)
186
+ * - Rebase: commits were rebased onto target branch
187
+ *
188
+ * @param pr - Pull request data
189
+ * @returns Merge method or undefined if cannot determine
190
+ */
191
+ export declare function detectMergeMethod(pr: GitHubPullRequest): 'merge' | 'squash' | 'rebase' | undefined;
192
+ /**
193
+ * Fetch PR data for a list of branches
194
+ *
195
+ * Efficiently batch-fetches merged PRs from GitHub and creates a map
196
+ * of branch name → PR data for quick lookups during enrichment.
197
+ *
198
+ * @param repository - Repository in owner/repo format
199
+ * @param _branches - Branch names (reserved for future filtering)
200
+ * @returns Map of branch name → PR data
201
+ * @throws Error if gh CLI is not available
202
+ */
203
+ export declare function fetchPRDataForBranches(repository: string, _branches: string[]): Promise<Map<string, GitHubPullRequest>>;
204
+ /**
205
+ * Enrich branch analyses with GitHub PR data
206
+ *
207
+ * Populates the githubFacts field in each analysis by matching branches
208
+ * to merged PRs. This helps identify squash-merged branches that git
209
+ * doesn't recognize as merged.
210
+ *
211
+ * @param analyses - Branch analyses to enrich
212
+ * @param repository - Repository in owner/repo format
213
+ * @throws Error if gh CLI is not available
214
+ */
215
+ export declare function enrichWithGitHubData(analyses: BranchAnalysis[], repository: string): Promise<void>;
216
+ /**
217
+ * Result of branch cleanup operation
218
+ */
219
+ export interface CleanupResult {
220
+ /** Context about the cleanup operation */
221
+ context: CleanupContext;
222
+ /** Branches that were auto-deleted */
223
+ autoDeleted: Array<{
224
+ name: string;
225
+ reason: string;
226
+ recoveryCommand: string;
227
+ }>;
228
+ /** Branches that need manual review */
229
+ needsReview: Array<{
230
+ name: string;
231
+ verification: BranchGitFacts & Partial<BranchGitHubFacts>;
232
+ assessment: string;
233
+ deleteCommand: string;
234
+ recoveryCommand: string;
235
+ }>;
236
+ /** Summary statistics */
237
+ summary: {
238
+ autoDeletedCount: number;
239
+ needsReviewCount: number;
240
+ totalBranchesAnalyzed: number;
241
+ };
242
+ /** Recovery information */
243
+ recoveryInfo: string;
244
+ }
245
+ /**
246
+ * Setup cleanup context and handle current branch switching
247
+ *
248
+ * If we're on a branch that needs cleanup, switch to default branch first.
249
+ *
250
+ * @returns Cleanup context
251
+ */
252
+ export declare function setupCleanupContext(): Promise<CleanupContext>;
253
+ /**
254
+ * Generate assessment text for a branch needing review
255
+ */
256
+ export declare function generateAssessment(gitFacts: BranchGitFacts, githubFacts?: BranchGitHubFacts): string;
257
+ /**
258
+ * Generate assessment for branch with deleted remote
259
+ */
260
+ export declare function generateDeletedRemoteAssessment(gitFacts: BranchGitFacts, githubFacts?: BranchGitHubFacts): string;
261
+ /**
262
+ * Try to delete a safe branch and return result
263
+ */
264
+ export declare function tryDeleteBranch(gitFacts: BranchGitFacts): {
265
+ deleted: boolean;
266
+ error?: string;
267
+ };
268
+ /**
269
+ * Categorize branches into auto-delete and needs-review
270
+ */
271
+ export declare function categorizeBranches(analyses: BranchAnalysis[]): {
272
+ autoDeleted: CleanupResult['autoDeleted'];
273
+ needsReview: CleanupResult['needsReview'];
274
+ };
275
+ /**
276
+ * Perform comprehensive branch cleanup
277
+ *
278
+ * This is the main entry point for branch cleanup. It:
279
+ * 1. Sets up context and switches branches if needed
280
+ * 2. Gathers all local branches
281
+ * 3. Analyzes each branch (git facts + GitHub enrichment)
282
+ * 4. Categorizes branches (auto-delete vs needs-review)
283
+ * 5. Deletes safe branches
284
+ * 6. Returns structured result with YAML-compatible format
285
+ *
286
+ * @returns Cleanup result with detailed analysis
287
+ */
288
+ export declare function cleanupBranches(): Promise<CleanupResult>;
289
+ //# sourceMappingURL=branch-cleanup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"branch-cleanup.d.ts","sourceRoot":"","sources":["../src/branch-cleanup.ts"],"names":[],"mappings":"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"}