feat: Use feature title for auto-generated worktree branch names#604
feat: Use feature title for auto-generated worktree branch names#604kevinisyoung wants to merge 3 commits intoAutoMaker-Org:v0.13.0rcfrom
Conversation
Instead of generic timestamp-based names like `feature/main-1768848108952-j7ra`, auto-generated worktree branches now use the feature title: `feature/add-user-authentication-1768848108952` This makes it easier to identify which features are in which worktrees: - Within Automaker's worktree panel and tabs - In the terminal and IDE - In git logs and branch listings When no title is provided (common case where users enter description only): - AI generates a title from the description BEFORE creating the worktree - The generated title is used for both the branch name and feature title - Falls back to first 60 chars of description if title generation fails Changes: - Slugify feature title (lowercase, replace special chars with hyphens) - Limit slug to 50 chars to keep branch names reasonable - Keep timestamp suffix for uniqueness - Updated both handleAddFeature and handleUpdateFeature Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. 📝 WalkthroughWalkthroughAuto-generates branch names from feature titles (using Electron API when title missing), slugifies title plus timestamp to form Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant UI as "UI (useBoardActions)"
participant Electron as "Electron API\napi.features.generateTitle"
participant Git as "Worktree Service"
participant Server as "Feature API"
User->>UI: Create/Update feature (workMode=auto)
UI->>UI: title present? → needsTitleGeneration?
alt title needs generation
UI->>Electron: generateTitle(description)
Electron-->>UI: generatedTitle / error
UI->>UI: titleForBranch = generatedTitle || descriptionSnippet
UI->>UI: titleWasGenerated = !!generatedTitle
else use existing title or description
UI->>UI: titleForBranch = existing title || descriptionSnippet
end
UI->>UI: titleSlug = slugify(titleForBranch)[:50] or "untitled"
UI->>Git: create worktree branch "feature/{titleSlug}-{timestamp}"
alt worktree created
Git-->>UI: success
UI->>Server: create/update feature (include generated title if titleWasGenerated)
Server-->>UI: persisted feature
UI->>UI: possibly run background title generation/update (async)
else failure
Git-->>UI: error
UI->>User: show error / fallback behavior
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested labels
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Summary of ChangesHello @kevinisyoung, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request significantly enhances the clarity and usability of auto-generated Git worktree branch names. By leveraging feature titles, either explicitly provided or intelligently generated from descriptions, the system now creates more descriptive and human-readable branch names. This change streamlines the identification of worktrees across various interfaces, improving developer workflow and reducing cognitive load when managing multiple features. Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@apps/ui/src/components/views/board-view/hooks/use-board-actions.ts`:
- Around line 120-143: When workMode === 'auto' and both featureData.title and
featureData.description are empty/whitespace, titleForBranch remains empty and
later slug generation yields malformed names; after the current title-generation
block (which uses getElectronAPI() and api.features.generateTitle and sets
titleForBranch/titleWasGenerated), ensure you validate and set a safe fallback:
if titleForBranch.trim() === '' assign a deterministic default (e.g.,
"untitled-feature" or "feature") or include a timestamp suffix so branch slug
isn't empty; update the use-board-actions hook to perform this fallback before
slug generation and log via logger when the fallback is used.
🧹 Nitpick comments (4)
apps/ui/src/components/views/board-view/hooks/use-board-actions.ts (4)
154-163: Consider guarding against empty slug after processing.If
titleForBranchprocesses to an empty slug (e.g., only special characters), the branch name becomesfeature/-{timestamp}with a leading hyphen after the slash. While git allows this, it's unconventional.Suggested improvement
const titleSlug = titleForBranch .toLowerCase() .replace(/[^a-z0-9]+/g, '-') .replace(/^-|-$/g, '') - .substring(0, 50); + .substring(0, 50) || 'feature'; const timestamp = Date.now(); finalBranchName = `feature/${titleSlug}-${timestamp}`;
309-332: Duplicated title generation logic could be extracted to a helper.This block (lines 309-332) is nearly identical to lines 120-143 in
handleAddFeature. Consider extracting this into a shared helper function to improve maintainability and reduce duplication.Example helper extraction
async function generateTitleForBranch( existingTitle: string, description: string, workMode: 'current' | 'auto' | 'custom' ): Promise<{ title: string; wasGenerated: boolean }> { let titleForBranch = existingTitle; let titleWasGenerated = false; if (workMode === 'auto' && !existingTitle.trim() && description.trim()) { const api = getElectronAPI(); if (api?.features?.generateTitle) { try { const result = await api.features.generateTitle(description); if (result.success && result.title) { titleForBranch = result.title; titleWasGenerated = true; } } catch (error) { logger.error('Error generating title for branch name:', error); } } if (!titleForBranch.trim()) { titleForBranch = description.substring(0, 60); } } return { title: titleForBranch, wasGenerated: titleWasGenerated }; }
339-351: Branch slug generation is also duplicated.The slug creation logic (lines 342-348) is identical to lines 157-161. This could be extracted alongside the title generation helper, or as a separate
createBranchSlugutility.Example utility
function createBranchSlug(title: string, maxLength = 50): string { return title .toLowerCase() .replace(/[^a-z0-9]+/g, '-') .replace(/^-+|-+$/g, '') .substring(0, maxLength) || 'feature'; }
269-280: Stale dependency:getPrimaryWorktreeBranchis no longer used.
getPrimaryWorktreeBranchappears in the dependency array at line 278 but is not used withinhandleAddFeatureafter the changes removed base-branch-based naming. The same applies tohandleUpdateFeatureat line 453.Remove unused dependency
[ addFeature, persistFeatureCreate, persistFeatureUpdate, updateFeature, saveCategory, currentProject, onWorktreeCreated, onWorktreeAutoSelect, - getPrimaryWorktreeBranch, features, ]And similarly for
handleUpdateFeature:[ updateFeature, persistFeatureUpdate, saveCategory, setEditingFeature, currentProject, onWorktreeCreated, - getPrimaryWorktreeBranch, features, ]
There was a problem hiding this comment.
Code Review
This pull request introduces a great improvement by using feature titles for auto-generated worktree branch names, making them much more descriptive. The implementation correctly handles cases where a title is missing by generating one from the description. My review focuses on a couple of areas for improvement: there's significant code duplication between handleAddFeature and handleUpdateFeature that could be refactored into a helper function. I also found a minor bug in the slugification logic that could produce invalid branch names, and an inconsistency in how background title generation is handled between adding and updating features. Addressing these points will make the implementation more robust and maintainable.
apps/ui/src/components/views/board-view/hooks/use-board-actions.ts
Outdated
Show resolved
Hide resolved
| const finalUpdates = { | ||
| ...restUpdates, | ||
| title: updates.title, | ||
| title: titleWasGenerated ? titleForBranch : updates.title, | ||
| branchName: finalBranchName, | ||
| }; |
There was a problem hiding this comment.
There's an inconsistency here compared to handleAddFeature. In handleAddFeature, if a title isn't generated synchronously for the branch name, needsTitleGeneration is set to true, and a background task is kicked off to generate the title for the feature. This logic seems to be missing in handleUpdateFeature.
As a result, if a user updates a feature to use 'auto' worktree mode without a title, and the synchronous title generation fails, the feature's title will remain empty, even though a branch is created.
For consistency, you should consider adding the background title generation logic here as well, similar to what's done in handleAddFeature.
| if (workMode === 'auto' && !featureData.title.trim() && featureData.description.trim()) { | ||
| // Generate title first so we can use it for the branch name | ||
| const api = getElectronAPI(); | ||
| if (api?.features?.generateTitle) { | ||
| try { | ||
| const result = await api.features.generateTitle(featureData.description); | ||
| if (result.success && result.title) { | ||
| titleForBranch = result.title; | ||
| titleWasGenerated = true; | ||
| } | ||
| } catch (error) { | ||
| logger.error('Error generating title for branch name:', error); | ||
| } | ||
| } | ||
| // If title generation failed, fall back to first part of description | ||
| if (!titleForBranch.trim()) { | ||
| titleForBranch = featureData.description.substring(0, 60); | ||
| } | ||
| } | ||
|
|
||
| // Determine final branch name based on work mode: | ||
| // - 'current': No branch name, work on current branch (no worktree) | ||
| // - 'auto': Auto-generate branch name based on current branch | ||
| // - 'auto': Auto-generate branch name based on feature title | ||
| // - 'custom': Use the provided branch name | ||
| let finalBranchName: string | undefined; | ||
|
|
||
| if (workMode === 'current') { | ||
| // No worktree isolation - work directly on current branch | ||
| finalBranchName = undefined; | ||
| } else if (workMode === 'auto') { | ||
| // Auto-generate a branch name based on primary branch (main/master) and timestamp | ||
| // Always use primary branch to avoid nested feature/feature/... paths | ||
| const baseBranch = | ||
| (currentProject?.path ? getPrimaryWorktreeBranch(currentProject.path) : null) || 'main'; | ||
| // Auto-generate a branch name based on feature title and timestamp | ||
| // Create a slug from the title: lowercase, replace non-alphanumeric with hyphens | ||
| const titleSlug = titleForBranch | ||
| .toLowerCase() | ||
| .replace(/[^a-z0-9]+/g, '-') // Replace non-alphanumeric sequences with hyphens | ||
| .replace(/^-|-$/g, '') // Remove leading/trailing hyphens | ||
| .substring(0, 50); // Limit length to keep branch names reasonable | ||
| const timestamp = Date.now(); | ||
| const randomSuffix = Math.random().toString(36).substring(2, 6); | ||
| finalBranchName = `feature/${baseBranch}-${timestamp}-${randomSuffix}`; | ||
| finalBranchName = `feature/${titleSlug}-${timestamp}`; |
There was a problem hiding this comment.
The logic for generating a branch name in 'auto' mode, including title generation and slugification, is duplicated between handleAddFeature and handleUpdateFeature (lines 314-348). To improve maintainability and adhere to the DRY principle, consider extracting this logic into a shared helper function.
…s.ts Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
- Add 'untitled' fallback when slug is empty (e.g., title with only special chars) - Remove unused getPrimaryWorktreeBranch from dependency arrays Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
@kevinisyoung can you review all comments, including nitpicks (Consider guarding against empty slug after processing, Branch slug generation is also duplicated, Stale dependency: getPrimaryWorktreeBranch is no longer used, etc). Also IF the comments are resolved, mark them as resolved. Thx. |
Instead of generating random branch names like `feature/main-1737547200000-tt2v`, this change creates human-readable branch names based on the feature title: `feature/add-user-authentication-a3b2` Changes: - Generate branch name slug from feature title (lowercase, alphanumeric, hyphens) - Use 4-character random suffix for uniqueness instead of timestamp - If no title provided, generate one from description first (for auto worktree mode) - Fall back to 'untitled' if both title and description are empty - Fix: Apply substring limit before removing trailing hyphens to prevent malformed branch names when truncation occurs at a hyphen position This makes it much easier to identify which worktree corresponds to which feature when working with multiple features simultaneously. Closes AutoMaker-Org#604
…es (#655) * feat(ui): generate meaningful worktree branch names from feature titles Instead of generating random branch names like `feature/main-1737547200000-tt2v`, this change creates human-readable branch names based on the feature title: `feature/add-user-authentication-a3b2` Changes: - Generate branch name slug from feature title (lowercase, alphanumeric, hyphens) - Use 4-character random suffix for uniqueness instead of timestamp - If no title provided, generate one from description first (for auto worktree mode) - Fall back to 'untitled' if both title and description are empty - Fix: Apply substring limit before removing trailing hyphens to prevent malformed branch names when truncation occurs at a hyphen position This makes it much easier to identify which worktree corresponds to which feature when working with multiple features simultaneously. Closes #604 * fix(ui): preserve existing branch name in auto mode when editing features When editing a feature that already has a branch name assigned, preserve it instead of generating a new one. This prevents orphaning existing worktrees when users edit features in auto worktree mode.
Summary
Auto-generated worktree branches now use the feature title instead of generic timestamp-based names.
Before:
feature/main-1768848108952-j7raAfter:
feature/add-user-authentication-1768848108952Benefits
This makes it easier to identify which features are in which worktrees:
Implementation
handleAddFeatureandhandleUpdateFeaturePre-submission Checklist
v0.13.0rc)npm run test:all- 1718 passed)npm run build)🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Improvements
✏️ Tip: You can customize this high-level summary in your review settings.