Skip to content

Conversation

@webdevcody
Copy link
Collaborator

@webdevcody webdevcody commented Dec 18, 2025

  • Introduced branchCardCounts prop to various components to display unarchived card counts per branch.
  • Updated BranchAutocomplete, BoardView, AddFeatureDialog, EditFeatureDialog, BranchSelector, WorktreePanel, and WorktreeTab to utilize the new prop for enhanced branch management visibility.
  • Enhanced user experience by showing card counts alongside branch names in relevant UI elements.

Summary by CodeRabbit

  • New Features

    • Branch selectors, autocomplete, add/edit dialogs, worktree tabs and panels now display per-branch unarchived card count badges.
  • Bug Fixes / UX

    • Delete-worktree dialog shows a warning with the number of affected features when removing a branch.
    • Worktree tabs show count badges only when >0 for clearer UI.
  • Other

    • Worktrees are created/validated at feature add/edit time; initial-commit handling added for reliable worktree creation.

✏️ Tip: You can customize this high-level summary in your review settings.

- Introduced branchCardCounts prop to various components to display unarchived card counts per branch.
- Updated BranchAutocomplete, BoardView, AddFeatureDialog, EditFeatureDialog, BranchSelector, WorktreePanel, and WorktreeTab to utilize the new prop for enhanced branch management visibility.
- Enhanced user experience by showing card counts alongside branch names in relevant UI elements.
@coderabbitai
Copy link

coderabbitai bot commented Dec 18, 2025

Note

Other AI code review bot(s) detected

CodeRabbit 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.

Walkthrough

Adds propagation of a memoized branchCardCounts map through branch selectors, dialogs, and worktree UI; client now attempts server-assisted worktree creation on feature add/update; server auto-mode stops creating worktrees on-demand and only uses pre-existing worktrees or falls back to the project path.

Changes

Cohort / File(s) Summary
Board view computation & refs
apps/app/src/components/views/board-view.tsx
Computes memoized branchCardCounts (unarchived-feature counts per branch), introduces refs to stabilize auto-start flows, speeds cadence, and passes branchCardCounts to child components.
Branch autocomplete / selector
apps/app/src/components/ui/branch-autocomplete.tsx, apps/app/src/components/views/board-view/shared/branch-selector.tsx
Add optional branchCardCounts?: Record<string, number> prop; BranchAutocomplete uses it to derive per-branch badge when provided, preserving prior logic otherwise.
Dialogs: add / edit feature
apps/app/src/components/views/board-view/dialogs/add-feature-dialog.tsx, apps/app/src/components/views/board-view/dialogs/edit-feature-dialog.tsx
Thread branchCardCounts into dialog props and pass to BranchSelector; adjust effect dependencies and formatting.
Worktree panel & tab
apps/app/src/components/views/board-view/worktree-panel/types.ts, apps/app/src/components/views/board-view/worktree-panel/worktree-panel.tsx, apps/app/src/components/views/board-view/worktree-panel/components/worktree-tab.tsx
Add branchCardCounts prop to WorktreePanel; compute per-worktree cardCount from it and pass to WorktreeTab; WorktreeTab shows badge based on cardCount (replacing changedFilesCount/hasChanges condition).
Delete worktree dialog
apps/app/src/components/views/board-view/dialogs/delete-worktree-dialog.tsx
Add affectedFeatureCount?: number prop; when >0 render an orange warning block describing unassignment of features.
Worktree creation on add/update (client hook)
apps/app/src/components/views/board-view/hooks/use-board-actions.ts
Before add/update, attempts server-assisted Electron worktree create/verify when worktrees enabled and branch present; logs/toasts errors, calls onWorktreeCreated, and extends callback dependency arrays.
Auto-mode execution (server)
apps/server/src/services/auto-mode-service.ts
Remove on-demand worktree creation; executeFeature uses feature.branchName and only uses existing worktrees (falls back to project path with a warning) — deletes setupWorktree.
Worktree route precondition
apps/server/src/routes/worktree/common.ts, apps/server/src/routes/worktree/routes/create.ts
Add ensureInitialCommit(repoPath) and call it from worktree create handler to ensure an initial commit exists before worktree operations.
Tests: worktree timing & integration
apps/app/tests/worktree-integration.spec.ts, apps/server/tests/integration/services/auto-mode-service.integration.test.ts, apps/server/tests/integration/routes/worktree/create.integration.test.ts
Update tests to expect worktrees created at add/edit time; integration tests pre-create worktrees and validate server uses existing worktrees; add create-route test for initial-commit behavior.
Minor / formatting only
apps/app/src/components/session-manager.tsx
Import and state declaration reflow/formatting only; no behavior change.

Sequence Diagram(s)

mermaid
sequenceDiagram
autonumber
participant UI as Client UI
participant Hook as use-board-actions
participant Electron as Electron API (worktree create)
participant Server as App Server (persist)
participant Git as Git Worktree (fs)
UI->>Hook: Save feature with branchName
Hook->>Electron: create/verify worktree(branchName)
alt created / exists
Electron-->>Hook: worktree info (path)
Hook->>UI: onWorktreeCreated(worktree)
Hook->>Server: persist feature (with branchName)
Server-->>Hook: 200 OK
Hook->>Git: worktree directory observed (side-effect)
else creation failed
Electron-->>Hook: error
Hook->>UI: show toast(error)
Hook->>Server: persist feature (with branchName)
Server-->>Hook: 200 OK
end
note right of Server: Auto-mode (executeFeature) now only looks up existing worktrees\nand falls back to project path if none found

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Inspect branchCardCounts memo correctness and dependency list in board-view.tsx.
  • Verify prop typings/prop-drilling across BranchSelector, BranchAutocomplete, dialogs, and WorktreePanel.
  • Review use-board-actions additions (Electron API calls, error handling, onWorktreeCreated flow, deps) for race conditions and stale closures.
  • Confirm server auto-mode-service.ts removal of setupWorktree and fallback behavior do not break execution paths.
  • Check new worktree create-route precondition (ensureInitialCommit) and accompanying integration tests for correctness.

Possibly related PRs

Poem

🐇 I hopped through branches counting cards at play,

Badges now sparkle to show work on the way.
I nudged a worktree in place with a cheer,
Features find homes — the board feels near.
A nibble of code, a carrot, and cheer.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 7.69% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'feat: add branch card counts to UI components' clearly and concisely summarizes the main change: introducing a branchCardCounts prop across multiple UI components to display card counts by branch.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/cards-in-worktrees

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @webdevcody, 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 integrates a new feature across the application's UI to display the number of unarchived cards associated with each branch. This enhancement provides users with immediate visibility into the workload or active features linked to specific branches, improving overall branch management and user experience within the application.

Highlights

  • New branchCardCounts Prop: Introduced a new branchCardCounts prop across various UI components to display the number of unarchived cards associated with each branch.
  • Enhanced Branch Visibility: Updated BranchAutocomplete, BoardView, AddFeatureDialog, EditFeatureDialog, BranchSelector, WorktreePanel, and WorktreeTab to utilize this new prop, showing card counts alongside branch names.
  • Improved User Experience: The change aims to enhance branch management visibility, allowing users to quickly see the active workload on different branches.

🧠 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 Assist

The 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 /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

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 .gemini/ folder in the base of the repository. Detailed instructions can be found here.

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

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request successfully introduces the branchCardCounts prop to display unarchived card counts for branches across various UI components. The changes are well-propagated through the component tree, from BoardView where the counts are calculated, down to BranchAutocomplete and WorktreeTab where they are displayed. The logic for calculating and displaying the counts is correct. I have one suggestion to refactor the card count calculation for improved conciseness and readability.

Comment on lines 274 to 286
const branchCardCounts = useMemo(() => {
const counts: Record<string, number> = {};

// Count unarchived features (status !== "completed") per branch
hookFeatures.forEach((feature) => {
if (feature.status !== "completed") {
const branch = feature.branchName || "main";
counts[branch] = (counts[branch] || 0) + 1;
}
});

return counts;
}, [hookFeatures]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This useMemo hook can be made more concise by using the reduce method instead of forEach to calculate the branch card counts. This is a common pattern in functional programming and can make the code more readable and expressive.

  const branchCardCounts = useMemo(() => {
    return hookFeatures.reduce((counts, feature) => {
      if (feature.status !== "completed") {
        const branch = feature.branchName || "main";
        counts[branch] = (counts[branch] || 0) + 1;
      }
      return counts;
    }, {} as Record<string, number>);
  }, [hookFeatures]);

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a0efa5d and f0bea76.

📒 Files selected for processing (8)
  • apps/app/src/components/ui/branch-autocomplete.tsx (3 hunks)
  • apps/app/src/components/views/board-view.tsx (4 hunks)
  • apps/app/src/components/views/board-view/dialogs/add-feature-dialog.tsx (8 hunks)
  • apps/app/src/components/views/board-view/dialogs/edit-feature-dialog.tsx (3 hunks)
  • apps/app/src/components/views/board-view/shared/branch-selector.tsx (3 hunks)
  • apps/app/src/components/views/board-view/worktree-panel/components/worktree-tab.tsx (4 hunks)
  • apps/app/src/components/views/board-view/worktree-panel/types.ts (1 hunks)
  • apps/app/src/components/views/board-view/worktree-panel/worktree-panel.tsx (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
apps/app/src/components/views/board-view/worktree-panel/worktree-panel.tsx (2)
apps/app/src/components/views/board-view/worktree-panel/components/worktree-tab.tsx (1)
  • WorktreeTab (46-194)
apps/app/src/components/views/board-view/worktree-panel/components/index.ts (1)
  • WorktreeTab (3-3)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build
  • GitHub Check: e2e
🔇 Additional comments (9)
apps/app/src/components/views/board-view/worktree-panel/types.ts (1)

38-38: LGTM! Clean type addition.

The optional branchCardCounts prop is well-typed and clearly documented. The comment explains the mapping purpose effectively.

apps/app/src/components/views/board-view.tsx (2)

851-851: LGTM! Clean prop threading.

The branchCardCounts prop is correctly passed to WorktreePanel, enabling branch-aware card count display.


948-948: LGTM! Consistent prop threading to dialogs.

The branchCardCounts prop is correctly propagated to both AddFeatureDialog and EditFeatureDialog, maintaining consistency across the feature creation and editing flows.

Also applies to: 964-964

apps/app/src/components/views/board-view/shared/branch-selector.tsx (1)

13-13: LGTM! Clean prop threading.

The branchCardCounts prop is properly typed, destructured, and forwarded to BranchAutocomplete. The implementation is straightforward and correct.

Also applies to: 25-25, 74-74

apps/app/src/components/views/board-view/worktree-panel/worktree-panel.tsx (1)

114-154: LGTM! Clean card count mapping.

The logic correctly maps branchCardCounts to per-worktree cardCount using optional chaining, and passes it to WorktreeTab. The implementation handles undefined values gracefully.

apps/app/src/components/views/board-view/dialogs/edit-feature-dialog.tsx (1)

80-80: LGTM! Consistent prop threading.

The branchCardCounts prop is properly added to the interface, destructured, and forwarded to BranchSelector. The implementation is consistent with the AddFeatureDialog pattern.

Also applies to: 94-94, 394-394

apps/app/src/components/views/board-view/worktree-panel/components/worktree-tab.tsx (1)

12-12: LGTM! Clean badge rendering logic.

The cardCount prop is properly typed and used to conditionally render the card count badge. The logic correctly handles edge cases:

  • Badge only appears when cardCount is defined and greater than 0
  • Rendering is consistent across both main and non-main worktrees
  • Zero counts are appropriately hidden

Also applies to: 48-48, 102-106, 145-149

apps/app/src/components/views/board-view/dialogs/add-feature-dialog.tsx (2)

76-76: LGTM! Clean prop threading.

The branchCardCounts prop is properly added to the interface, destructured, and forwarded to BranchSelector. The implementation is consistent with the dialog pattern used throughout.

Also applies to: 91-91, 414-414


143-149: Good practice: expanded dependency array.

The useEffect dependency array now includes defaultPlanningMode and defaultRequirePlanApproval, ensuring the effect re-runs when these defaults change. This maintains proper synchronization with store values.

- Fix branch fallback logic: use nullish coalescing (??) instead of || to handle empty strings correctly (empty string represents unassigned features, not main branch)
- Refactor branchCardCounts calculation: use reduce instead of forEach for better conciseness and readability
- Fix badge semantics in BranchAutocomplete: check branchCardCounts !== undefined first to ensure numeric badges (including 0) only appear when actual count data exists, while 'default' is reserved for when count data is unavailable
- Consolidated imports in session-manager.tsx for cleaner code.
- Improved state initialization formatting for better readability.
- Updated board-view.tsx to enhance feature management, including the use of refs to track running tasks and prevent unnecessary effect re-runs.
- Added affectedFeatureCount prop to DeleteWorktreeDialog for better user feedback on feature assignments.
- Refactored useBoardActions to ensure worktrees are created when features are added or updated, improving overall workflow efficiency.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/server/src/services/auto-mode-service.ts (1)

554-554: Fix type mismatch causing pipeline failure.

The pipeline is failing because branchName is string | undefined but tempRunningFeature.branchName expects string | null. Convert undefined to null to match the interface.

🔎 Proposed fix
-      tempRunningFeature.branchName = branchName;
+      tempRunningFeature.branchName = branchName ?? null;
♻️ Duplicate comments (2)
apps/app/src/components/views/board-view/hooks/use-board-actions.ts (1)

176-211: Duplicate code - see comment on lines 107-142.

This block is identical to the worktree creation logic in handleAddFeature. Refer to the refactoring suggestion on lines 107-142.

apps/app/src/components/views/board-view.tsx (1)

1127-1132: Consistent feature reset logic on worktree deletion.

The feature reset logic correctly matches the pattern in handleRemovedWorktrees, updating both local state and persisting changes. The type assertion concern for Line 1129 is the same as noted for Line 317.

🧹 Nitpick comments (3)
apps/app/src/components/views/board-view/hooks/use-board-actions.ts (1)

828-829: Clarify comment to avoid confusion with new worktree creation logic.

The comment "No worktree creation on client" might be confusing given that worktrees are now created client-side in handleAddFeature and handleUpdateFeature. Consider rephrasing to clarify this specifically refers to the start-next-features flow.

🔎 Suggested clarification
-    // Start only one feature per keypress (user must press again for next)
-    // Simplified: No worktree creation on client - server derives workDir from feature.branchName
+    // Start only one feature per keypress (user must press again for next)
+    // Note: Worktree is pre-created during add/update; server derives workDir from feature.branchName at execution
     await handleStartImplementation(featureToStart);
apps/app/src/components/views/board-view.tsx (2)

316-323: Simplify the type assertion for resetting branchName.

The double type assertion null as unknown as string | undefined is unnecessarily complex. Consider using undefined directly or updating the type definition to properly accept null.

🔎 Proposed simplification
-          const updates = { branchName: null as unknown as string | undefined };
+          const updates = { branchName: undefined };

This achieves the same result with clearer intent. The same pattern is repeated at Line 1129.


699-728: Consider optimizing callback dependencies for performance.

Both handlePlanApprove and handlePlanReject now include hookFeatures in their dependency arrays, causing them to be recreated on every feature update. Since they only need to find a single feature by ID, consider using a ref pattern (similar to hookFeaturesRef already used elsewhere) to avoid frequent callback recreation.

🔎 Suggested optimization

Access the current feature version using the existing hookFeaturesRef:

  const handlePlanApprove = useCallback(
    async (editedPlan?: string) => {
      // ... existing code ...
      try {
        // ... existing code ...
        if (result.success) {
-         const currentFeature = hookFeatures.find((f) => f.id === featureId);
+         const currentFeature = hookFeaturesRef.current.find((f) => f.id === featureId);
          // ... rest of the code ...
        }
      }
      // ...
    },
    [
      pendingPlanApproval,
      currentProject,
      setPendingPlanApproval,
      updateFeature,
      loadFeatures,
-     hookFeatures,
    ]
  );

Apply the same pattern to handlePlanReject.

Also applies to: 755-784

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 81d631e and 18fa0f3.

📒 Files selected for processing (5)
  • apps/app/src/components/session-manager.tsx (3 hunks)
  • apps/app/src/components/views/board-view.tsx (18 hunks)
  • apps/app/src/components/views/board-view/dialogs/delete-worktree-dialog.tsx (4 hunks)
  • apps/app/src/components/views/board-view/hooks/use-board-actions.ts (4 hunks)
  • apps/server/src/services/auto-mode-service.ts (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • apps/app/src/components/session-manager.tsx
🧰 Additional context used
🧬 Code graph analysis (2)
apps/server/src/services/auto-mode-service.ts (1)
apps/app/src/components/views/board-view/worktree-panel/hooks/use-worktrees.ts (1)
  • useWorktrees (15-105)
apps/app/src/components/views/board-view/hooks/use-board-actions.ts (3)
apps/app/src/components/views/board-view/worktree-panel/hooks/use-worktrees.ts (1)
  • useWorktrees (15-105)
apps/app/src/lib/electron.ts (1)
  • getElectronAPI (549-559)
apps/app/tests/utils/views/board.ts (1)
  • addFeature (197-205)
🪛 GitHub Actions: E2E Tests
apps/server/src/services/auto-mode-service.ts

[error] 554-554: Type 'string | undefined' is not assignable to type 'string | null'.

🪛 GitHub Actions: PR Build Check
apps/server/src/services/auto-mode-service.ts

[error] 554-554: TS2322: Type 'string | undefined' is not assignable to type 'string | null'.

🔇 Additional comments (15)
apps/app/src/components/views/board-view/dialogs/delete-worktree-dialog.tsx (4)

15-15: LGTM: FileWarning icon import added.

The import is correctly structured and the icon is appropriately used in the affected features warning block.


33-34: LGTM: Well-documented optional prop.

The JSDoc comment clearly explains the purpose, and making it optional allows for gradual adoption across call sites.


43-43: LGTM: Sensible default value.

The default value of 0 elegantly handles the optional prop and prevents the warning from showing when the count is unknown or not provided.


106-116: LGTM: Excellent user communication for data impact.

The warning block effectively communicates the consequences of deleting a worktree with assigned features:

  • Clear messaging: Users understand that features will be unassigned and moved to the main worktree.
  • Appropriate severity: Orange theme signals a warning that's more serious than a notice but less critical than an error.
  • Correct pluralization: The logic handles singular and plural cases correctly across all three conditionals.
  • Consistent styling: Matches the pattern established by the uncommitted changes warning below.
  • Good prioritization: Appearing before the changes warning emphasizes the data impact.
apps/app/src/components/views/board-view/hooks/use-board-actions.ts (3)

85-86: LGTM!

Clear comments explaining the worktree pre-creation strategy.


154-154: LGTM!

Dependency array correctly updated to include useWorktrees, currentProject, and onWorktreeCreated.


225-225: LGTM!

Dependency array correctly updated to match the new closure dependencies.

apps/server/src/services/auto-mode-service.ts (2)

523-525: Verify downstream handling when branchName is undefined.

The code assigns branchName (which can be undefined from feature.branchName) directly to tempRunningFeature.branchName at line 554 without a null check. While there's a conditional check at line 529 for worktree lookup, the main assignment proceeds regardless. Ensure this doesn't cause type errors or silent failures if the feature lacks an associated branch.


527-545: Worktree lookup and fallback logic is correct.

The approach of pre-creating worktrees when features are added/edited (via the UI API), then looking them up during execution with a graceful fallback to the project path, is sound. The warning log at lines 541-542 will effectively help identify cases where worktrees are missing, whether due to manual deletion, creation failures, or edge cases.

apps/app/src/components/views/board-view.tsx (6)

273-282: LGTM! Previous concerns resolved.

The branchCardCounts calculation correctly addresses both previous review comments: it now uses reduce for a more functional approach and employs nullish coalescing (??) to properly handle empty strings as distinct from null/undefined.


432-442: LGTM! Proper ref pattern to prevent effect churn.

The ref pattern for runningAutoTasks and handleStartImplementation correctly prevents the auto-mode effect from re-running when these values change, which would otherwise clear pendingFeaturesRef and cause concurrency issues.


511-513: LGTM! Consistent ref usage in auto-mode effect.

The ref-based access patterns are correctly implemented throughout the auto-mode effect, preventing unnecessary re-runs while maintaining access to current values.

Also applies to: 568-571, 597-597


880-880: LGTM! branchCardCounts correctly threaded to UI components.

The branchCardCounts prop is consistently passed to WorktreePanel, AddFeatureDialog, and EditFeatureDialog, aligning with the PR objectives to display per-branch card counts throughout the UI.

Also applies to: 977-977, 993-993


1115-1121: LGTM! Clearer inline calculation.

The inline affectedFeatureCount calculation using filter is more explicit and easier to understand than the previous implementation.


623-624: LGTM! Minor improvements to comments, formatting, and type checks.

The additional comments explaining ref usage, formatting improvements, and more concise type checking all enhance code clarity without introducing issues.

Also applies to: 671-673, 795-795

Comment on lines 610 to +611
checkAndStartFeatures();
const interval = setInterval(checkAndStartFeatures, 3000);
const interval = setInterval(checkAndStartFeatures, 1000);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Read the file around lines 610-611 to see the actual comment and code
sed -n '600,620p' apps/app/src/components/views/board-view.tsx

Repository: AutoMaker-Org/automaker

Length of output: 659


Update comment to reflect actual interval timing.

The comment states "every 3 seconds" but the interval is set to 1000ms (1 second). Update the comment on line 609 to: // Check immediately, then every 1 second to match the implemented behavior.

🤖 Prompt for AI Agents
In apps/app/src/components/views/board-view.tsx around lines 609 to 611, the
inline comment incorrectly says "every 3 seconds" while the code calls
checkAndStartFeatures() immediately then sets setInterval(checkAndStartFeatures,
1000) (1 second). Update the comment on line 609 to read "// Check immediately,
then every 1 second" so it matches the implemented interval.

Comment on lines +107 to +142
// If worktrees enabled and a branch is specified, create the worktree now
// This ensures the worktree exists before the feature starts
if (useWorktrees && finalBranchName && currentProject) {
try {
const api = getElectronAPI();
if (api?.worktree?.create) {
const result = await api.worktree.create(
currentProject.path,
finalBranchName
);
if (result.success) {
console.log(
`[Board] Worktree for branch "${finalBranchName}" ${
result.worktree?.isNew ? "created" : "already exists"
}`
);
// Refresh worktree list in UI
onWorktreeCreated?.();
} else {
console.error(
`[Board] Failed to create worktree for branch "${finalBranchName}":`,
result.error
);
toast.error("Failed to create worktree", {
description: result.error || "An error occurred",
});
}
}
} catch (error) {
console.error("[Board] Error creating worktree:", error);
toast.error("Failed to create worktree", {
description:
error instanceof Error ? error.message : "An error occurred",
});
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

find apps -name "use-board-actions.ts" -type f

Repository: AutoMaker-Org/automaker

Length of output: 134


🏁 Script executed:

cat -n apps/app/src/components/views/board-view/hooks/use-board-actions.ts | sed -n '100,220p'

Repository: AutoMaker-Org/automaker

Length of output: 5249


🏁 Script executed:

# Verify the control flow - check if feature creation is conditional on worktree success
sed -n '107,152p' apps/app/src/components/views/board-view/hooks/use-board-actions.ts | grep -A 20 "^      }"

Repository: AutoMaker-Org/automaker

Length of output: 440


Extract duplicate worktree creation logic into a helper function.

Lines 107-142 and 176-211 contain identical worktree creation code (35+ lines) in handleAddFeature and handleUpdateFeature. Extract this into a reusable helper to reduce maintenance risk and inconsistency.

Clarify whether feature creation should proceed when worktree creation fails.

Currently, feature creation continues even if worktree creation fails—only an error toast is shown. Verify this is the intended behavior, as users may expect the operation to fail entirely if the worktree cannot be established. If intentional, document this design choice; otherwise, consider aborting feature creation on worktree failure.

- Modified test descriptions to clarify when worktrees are created during feature addition and editing.
- Updated assertions to verify that worktrees and branches are created as expected when features are added or edited.
- Enhanced test logic to ensure accurate verification of worktree existence and branch creation, reflecting recent changes in worktree management.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
apps/server/tests/integration/services/auto-mode-service.integration.test.ts (1)

50-68: Test setup correctly simulates client-side worktree creation.

The test now pre-creates the worktree before execution, aligning with the PR objective where worktrees are created upfront by the client rather than on-demand by the server. The Git command structure is correct and properly creates both the branch and worktree.

Minor: Use ES6 shorthand property syntax
       branchName: branchName,
+      branchName,
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 18fa0f3 and 275037c.

📒 Files selected for processing (2)
  • apps/app/tests/worktree-integration.spec.ts (5 hunks)
  • apps/server/tests/integration/services/auto-mode-service.integration.test.ts (3 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
apps/server/tests/integration/services/auto-mode-service.integration.test.ts (1)
apps/server/tests/integration/helpers/git-test-repo.ts (3)
  • createTestFeature (76-89)
  • listBranches (94-100)
  • listWorktrees (105-122)
🔇 Additional comments (3)
apps/server/tests/integration/services/auto-mode-service.integration.test.ts (1)

16-19: LGTM! Clean helper setup.

The execAsync helper correctly wraps the callback-based exec in a promise using promisify, enabling clean async/await usage for Git commands in the test.

apps/app/tests/worktree-integration.spec.ts (2)

813-819: LGTM! Assertions correctly validate the new worktree creation timing.

The test properly verifies that both the branch and worktree are created when the feature is added, which aligns with the PR's change to create worktrees at feature add/edit time rather than execution time.


2439-2447: LGTM! Edit feature test correctly validates new worktree creation behavior.

The test properly verifies that when editing a feature to use a new branch:

  1. The worktree is created during the edit operation (line 2443)
  2. The branch is created (line 2447)
  3. The feature data is updated with the new branch name (line 2451)

This correctly validates the new behavior where worktrees are created at edit time. The same 2000ms timeout concern mentioned in the earlier comment applies here as well.

Comment on lines +810 to +811
// Wait for feature to be saved and worktree to be created
await page.waitForTimeout(2000);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# First, find the test file and examine lines 810-811 with context
find . -name "worktree-integration.spec.ts" -type f 2>/dev/null | head -1

Repository: AutoMaker-Org/automaker

Length of output: 112


🏁 Script executed:

# Read the test file to see the actual code at lines 810-811
if [ -f "apps/app/tests/worktree-integration.spec.ts" ]; then
  wc -l "apps/app/tests/worktree-integration.spec.ts"
fi

Repository: AutoMaker-Org/automaker

Length of output: 115


🏁 Script executed:

# Search for worktree creation calls and await patterns
rg -n 'createWorktree|apiCreateWorktree' --type=ts -A 3 -B 3 2>/dev/null | head -100

Repository: AutoMaker-Org/automaker

Length of output: 7295


🏁 Script executed:

# Search for Dialog files that might contain worktree creation
fd -e ts -e tsx '.*Dialog' 2>/dev/null | grep -i feature | head -20

Repository: AutoMaker-Org/automaker

Length of output: 49


🏁 Script executed:

# Read the test file around lines 810-811 with full context
sed -n '800,820p' apps/app/tests/worktree-integration.spec.ts

Repository: AutoMaker-Org/automaker

Length of output: 795


🏁 Script executed:

# Read more context around the timeout to see the test logic
sed -n '782,845p' apps/app/tests/worktree-integration.spec.ts

Repository: AutoMaker-Org/automaker

Length of output: 2533


🏁 Script executed:

# Search for feature add/edit related dialog files
fd -type f \( -name "*AddFeature*" -o -name "*EditFeature*" -o -name "*Feature*Dialog*" \) --extension=ts --extension=tsx 2>/dev/null | head -20

Repository: AutoMaker-Org/automaker

Length of output: 49


🏁 Script executed:

# Search for worktree creation in source code (not tests)
rg -n 'createWorktree|createWorktreeDirectly' --type=ts -g '!tests' -g '!spec' -A 5 -B 2 | head -150

Repository: AutoMaker-Org/automaker

Length of output: 2160


🏁 Script executed:

# Search for confirmAddFeature implementation
rg -n 'confirmAddFeature|fillAddFeatureDialog|clickAddFeature' --type=ts -B 3 -A 10 | head -100

Repository: AutoMaker-Org/automaker

Length of output: 7926


🏁 Script executed:

# Search for feature creation API endpoint or handler
rg -n 'addFeature|createFeature' --type=ts -g '!tests' -A 5 -B 2 | head -150

Repository: AutoMaker-Org/automaker

Length of output: 11531


🏁 Script executed:

# Look for waitForNetworkIdle to see how other similar operations wait
rg -n 'waitForNetworkIdle|waitForResponse' apps/app/tests/worktree-integration.spec.ts -B 2 -A 2 | head -60

Repository: AutoMaker-Org/automaker

Length of output: 1748


🏁 Script executed:

# Find confirmAddFeature implementation
rg -n 'export.*confirmAddFeature|function confirmAddFeature' --type=ts -A 15

Repository: AutoMaker-Org/automaker

Length of output: 1171


🏁 Script executed:

# Check persistFeatureCreate to see if it awaits worktree
rg -n 'persistFeatureCreate' --type=ts -A 10 -B 2 | head -80

Repository: AutoMaker-Org/automaker

Length of output: 7352


🏁 Script executed:

# Search for where worktree creation happens during feature add
rg -n 'onWorktreeCreated|useWorktrees' --type=ts apps/app/src/components/views/board-view/hooks/use-board-actions.ts -A 5 -B 5 | head -100

Repository: AutoMaker-Org/automaker

Length of output: 3825


Replace page.waitForTimeout(2000) with a proper wait condition for worktree creation.

The hard wait masks an underlying async operation. While production code properly awaits api.worktree.create() when adding features with branches (lines 109-124 in use-board-actions.ts), the test helper confirmAddFeature() only waits for the dialog to close, not for the background worktree creation to complete. The timeout was doubled from 1000ms to 2000ms to accommodate slower systems—a sign that relying on arbitrary delays is flaky.

Instead, replace the hard wait with a condition-based wait:

await expect(page).toHaveURL(/.*/, { timeout: 5000 }); // Wait for any pending network

Or use a more specific check that the worktree directory exists or a related UI state updates, ensuring the test reliably detects completion regardless of system performance.

🤖 Prompt for AI Agents
In apps/app/tests/worktree-integration.spec.ts around lines 810-811, replace the
hard sleep await page.waitForTimeout(2000) with a deterministic wait for the
worktree creation to finish: update the test to wait on a condition (e.g. use
Playwright's expect(page).toHaveURL(/.*/, { timeout: 5000 }) to wait for pending
navigation/network, or better assert a specific UI change or existence of the
worktree directory/indicator that the background api.worktree.create()
completed); modify confirmAddFeature() or the test to await that condition
instead of relying on an arbitrary timeout so the test is robust across
machines.

Comment on lines +100 to +113
// Verify branch exists (was created when worktree was created)
const branches = await listBranches(testRepo.path);
expect(branches).toContain("feature/test-feature-1");
expect(branches).toContain(branchName);

// Verify worktree exists and is being used
// The service should have found and used the worktree (check via logs)
// We can verify the worktree exists by checking git worktree list
const worktrees = await listWorktrees(testRepo.path);
expect(worktrees.length).toBeGreaterThan(0);
// Verify that at least one worktree path contains our feature ID
const worktreePathsMatch = worktrees.some(wt =>
wt.includes("test-feature-1") || wt.includes(".worktrees")
);
expect(worktreePathsMatch).toBe(true);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Tighten the worktree verification logic.

The branch verification is correct, but the worktree check on lines 110-112 is overly permissive. The condition wt.includes(".worktrees") will pass if ANY worktree exists in the .worktrees directory, even if it's not for test-feature-1. This could lead to false positives if other tests leave worktrees behind.

Suggested fix: Verify the specific worktree path
-      // Verify that at least one worktree path contains our feature ID
-      const worktreePathsMatch = worktrees.some(wt => 
-        wt.includes("test-feature-1") || wt.includes(".worktrees")
-      );
-      expect(worktreePathsMatch).toBe(true);
+      // Verify that the worktree for our feature exists
+      const expectedWorktreePath = path.join(testRepo.path, ".worktrees", "test-feature-1");
+      const worktreeExists = worktrees.some(wt => wt === expectedWorktreePath);
+      expect(worktreeExists).toBe(true);

Alternatively, you can keep the current approach but remove the .worktrees check:

       const worktreePathsMatch = worktrees.some(wt => 
-        wt.includes("test-feature-1") || wt.includes(".worktrees")
+        wt.includes("test-feature-1")
       );
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Verify branch exists (was created when worktree was created)
const branches = await listBranches(testRepo.path);
expect(branches).toContain("feature/test-feature-1");
expect(branches).toContain(branchName);
// Verify worktree exists and is being used
// The service should have found and used the worktree (check via logs)
// We can verify the worktree exists by checking git worktree list
const worktrees = await listWorktrees(testRepo.path);
expect(worktrees.length).toBeGreaterThan(0);
// Verify that at least one worktree path contains our feature ID
const worktreePathsMatch = worktrees.some(wt =>
wt.includes("test-feature-1") || wt.includes(".worktrees")
);
expect(worktreePathsMatch).toBe(true);
// Verify branch exists (was created when worktree was created)
const branches = await listBranches(testRepo.path);
expect(branches).toContain(branchName);
// Verify worktree exists and is being used
// The service should have found and used the worktree (check via logs)
// We can verify the worktree exists by checking git worktree list
const worktrees = await listWorktrees(testRepo.path);
expect(worktrees.length).toBeGreaterThan(0);
// Verify that at least one worktree path contains our feature ID
const worktreePathsMatch = worktrees.some(wt =>
wt.includes("test-feature-1")
);
expect(worktreePathsMatch).toBe(true);
🤖 Prompt for AI Agents
In apps/server/tests/integration/services/auto-mode-service.integration.test.ts
around lines 100 to 113, the worktree verification is too permissive because
wt.includes(".worktrees") can match unrelated worktrees; change the assertion to
verify the specific worktree for this test by checking the worktree path
contains the feature identifier (e.g., "test-feature-1") or the exact expected
worktree directory/name used by the test, remove the generic ".worktrees" check,
and assert that at least one worktree path matches that specific criteria.

- Updated branchName assignment to use nullish coalescing, ensuring that unassigned features are correctly set to null instead of an empty string. This change improves the handling of feature states during the update process.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/server/src/services/auto-mode-service.ts (1)

731-731: Align branchName derivation with executeFeature changes.

Line 731 still uses a fallback pattern (feature?.branchName || 'feature/${featureId}') that was removed from executeFeature at line 525. This creates inconsistent behavior:

  • executeFeature: uses feature.branchName directly (no fallback)
  • followUpFeature: falls back to feature/${featureId} if branchName is missing

This inconsistency could cause followUpFeature to search for a worktree with branch feature/${featureId} when the feature has no branchName set, while executeFeature would use the project path directly.

🔎 Suggested fix for consistency
-    const branchName = feature?.branchName || `feature/${featureId}`;
+    const branchName = feature?.branchName;

And consider adding the same warning as suggested for executeFeature:

     if (useWorktrees && branchName) {
       // Try to find existing worktree for this branch
       worktreePath = await this.findExistingWorktreeForBranch(
         projectPath,
         branchName
       );

       if (worktreePath) {
         workDir = worktreePath;
         console.log(
           `[AutoMode] Follow-up using worktree for branch "${branchName}": ${workDir}`
         );
+      } else {
+        console.warn(
+          `[AutoMode] Follow-up: Worktree for branch "${branchName}" not found, using project path`
+        );
       }
+    } else if (useWorktrees && !branchName) {
+      console.warn(
+        `[AutoMode] Follow-up: Feature ${featureId} has no branchName set, using project path`
+      );
     }
🧹 Nitpick comments (1)
apps/server/src/services/auto-mode-service.ts (1)

523-545: Consider logging a warning when branchName is missing but useWorktrees is enabled.

The current logic only searches for a worktree when branchName exists (line 527). If branchName is undefined or empty, the code silently falls back to projectPath without any warning. This could be confusing for users who expect worktree isolation but unknowingly execute in the main project path.

🔎 Suggested enhancement
 const branchName = feature.branchName;

 if (useWorktrees && branchName) {
   // Try to find existing worktree for this branch
   // Worktree should already exist (created when feature was added/edited)
   worktreePath = await this.findExistingWorktreeForBranch(
     projectPath,
     branchName
   );

   if (worktreePath) {
     console.log(
       `[AutoMode] Using worktree for branch "${branchName}": ${worktreePath}`
     );
   } else {
     // Worktree doesn't exist - log warning and continue with project path
     console.warn(
       `[AutoMode] Worktree for branch "${branchName}" not found, using project path`
     );
   }
+} else if (useWorktrees && !branchName) {
+  // No branch name set for feature - log warning
+  console.warn(
+    `[AutoMode] Feature ${featureId} has no branchName set, using project path instead of worktree`
+  );
 }
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 275037c and 340e76c.

📒 Files selected for processing (1)
  • apps/server/src/services/auto-mode-service.ts (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
apps/server/src/services/auto-mode-service.ts (1)
apps/app/src/components/views/board-view/worktree-panel/hooks/use-worktrees.ts (1)
  • useWorktrees (15-105)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: e2e
  • GitHub Check: build
🔇 Additional comments (1)
apps/server/src/services/auto-mode-service.ts (1)

523-545: Client-side worktree creation is properly implemented with built-in idempotency and error handling.

The codebase shows worktrees are created in use-board-actions.ts when features are added/edited with a branch name. The implementation:

  • Calls api.worktree.create() immediately when a feature with branchName is created or edited (before persistence)
  • Handles idempotency: re-creating the same branch returns the existing worktree instead of erroring
  • Includes error handling with user-facing toast notifications (failures are not silent)
  • Falls back gracefully on the server: if a worktree isn't found at execution time, logs a warning and proceeds with the main project path

Valid edge cases to consider:

  1. Existing features created before this architectural change won't have worktrees; consider a migration strategy if needed
  2. Manual .automaker/features/*/feature.json edits bypass client-side worktree creation
  3. The dependency is intentional: the server assumes worktrees exist but gracefully degrades if missing

The current implementation is sound for new features going forward.

- Added a function to ensure that a git repository has at least one commit before executing worktree commands. This function creates an empty initial commit with a predefined message if the repository is empty.
- Updated the create route handler to call this function, ensuring smooth operation when adding worktrees to repositories without existing commits.
- Introduced integration tests to verify the creation of the initial commit when no commits are present in the repository.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
apps/server/tests/integration/routes/worktree/create.integration.test.ts (1)

1-68: Consider expanding test coverage for ensureInitialCommit behavior.

The test correctly verifies that an initial commit is created when HEAD is missing. However, consider adding tests for:

  1. Repository with existing commits - verify that ensureInitialCommit returns false and doesn't create an additional commit.
  2. Worktree creation success - verify that the worktree is actually created at the expected path after the initial commit.
  3. Git configuration missing - verify the error message when user.name or user.email are not configured.
💡 Example: Test for existing commits
it("does not create a commit when HEAD already exists", async () => {
  await initRepoWithoutCommit();
  
  // Create an initial commit manually
  await execAsync('git commit --allow-empty -m "existing commit"', { 
    cwd: repoPath! 
  });
  
  const handler = createCreateHandler();
  const json = vi.fn();
  const status = vi.fn().mockReturnThis();
  const req = {
    body: { projectPath: repoPath, branchName: "feature/with-head" },
  } as any;
  const res = { json, status } as any;

  await handler(req, res);

  // Should still succeed
  expect(json).toHaveBeenCalled();
  const payload = json.mock.calls[0][0];
  expect(payload.success).toBe(true);

  // Should still have exactly 1 commit (not 2)
  const { stdout: commitCount } = await execAsync(
    "git rev-list --count HEAD",
    { cwd: repoPath! }
  );
  expect(Number(commitCount.trim())).toBe(1);
});
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 340e76c and 18a2ed2.

📒 Files selected for processing (3)
  • apps/server/src/routes/worktree/common.ts (2 hunks)
  • apps/server/src/routes/worktree/routes/create.ts (2 hunks)
  • apps/server/tests/integration/routes/worktree/create.integration.test.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
apps/server/src/routes/worktree/common.ts (2)
apps/server/src/routes/templates/common.ts (2)
  • logger (11-11)
  • getErrorMessageShared (14-14)
apps/server/src/routes/app-spec/common.ts (1)
  • getErrorMessageShared (71-71)
apps/server/tests/integration/routes/worktree/create.integration.test.ts (2)
apps/server/src/routes/worktree/routes/create.ts (1)
  • createCreateHandler (77-181)
apps/server/src/routes/worktree/common.ts (1)
  • AUTOMAKER_INITIAL_COMMIT_MESSAGE (16-17)
apps/server/src/routes/worktree/routes/create.ts (1)
apps/server/src/routes/worktree/common.ts (1)
  • ensureInitialCommit (84-105)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: e2e
  • GitHub Check: build
🔇 Additional comments (3)
apps/server/src/routes/worktree/common.ts (1)

16-17: LGTM!

The constant is well-named and provides a clear, consistent commit message for auto-generated initial commits.

apps/server/src/routes/worktree/routes/create.ts (2)

15-21: LGTM!

The import is clean and properly organized with other common utilities.


102-103: LGTM! Excellent placement and documentation.

The ensureInitialCommit call is correctly positioned after the git repository validation and before any operations that reference HEAD. The comment clearly explains why this precondition is necessary, making the code maintainable.

This ensures that:

  • Line 106's findExistingWorktreeForBranch can safely check worktree branches
  • Line 137's git rev-parse --verify for branch checking works correctly
  • Line 152's default base = baseBranch || "HEAD" always has a valid HEAD to reference

Comment on lines +84 to +105
export async function ensureInitialCommit(repoPath: string): Promise<boolean> {
try {
await execAsync("git rev-parse --verify HEAD", { cwd: repoPath });
return false;
} catch {
try {
await execAsync(
`git commit --allow-empty -m "${AUTOMAKER_INITIAL_COMMIT_MESSAGE}"`,
{ cwd: repoPath }
);
logger.info(
`[Worktree] Created initial empty commit to enable worktrees in ${repoPath}`
);
return true;
} catch (error) {
const reason = getErrorMessageShared(error);
throw new Error(
`Failed to create initial git commit. Please commit manually and retry. ${reason}`
);
}
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check the test file mentioned (lines 20-23) and surrounding context
git ls-files "**/common.ts" | grep -E "test|spec" | head -5

Repository: AutoMaker-Org/automaker

Length of output: 108


🏁 Script executed:

#!/bin/bash
# Find test files related to worktree/common
find . -name "*.test.ts" -o -name "*.spec.ts" | xargs grep -l "ensureInitialCommit" 2>/dev/null | head -3

Repository: AutoMaker-Org/automaker

Length of output: 49


🏁 Script executed:

#!/bin/bash
# Search for git config setup in the codebase
echo "=== Searching for git config user setup ==="
rg "git config user\." --type ts

echo -e "\n=== Searching for execAsync git commands ==="
rg "execAsync.*git" -A 2 -B 1 --type ts | head -40

echo -e "\n=== Looking for test setup with git config ==="
rg "git config" --type ts -C 3 | head -50

Repository: AutoMaker-Org/automaker

Length of output: 7899


🏁 Script executed:

#!/bin/bash
# Look at the actual ensureInitialCommit function file
cat -n apps/server/src/routes/worktree/common.ts | sed -n '70,115p'

Repository: AutoMaker-Org/automaker

Length of output: 1424


🏁 Script executed:

#!/bin/bash
# Search for where ensureInitialCommit is called in the codebase
echo "=== Calls to ensureInitialCommit ==="
rg "ensureInitialCommit" --type ts -B 3 -A 3

Repository: AutoMaker-Org/automaker

Length of output: 1922


🏁 Script executed:

#!/bin/bash
# Check if there's any production setup that configures git
echo "=== Searching for git setup in production code ==="
rg "git config" apps/server/src --type ts

Repository: AutoMaker-Org/automaker

Length of output: 397


🏁 Script executed:

#!/bin/bash
# Check what getErrorMessageShared returns and how it handles git errors
rg "getErrorMessageShared" apps/server/src --type ts -A 5 | head -40

Repository: AutoMaker-Org/automaker

Length of output: 2634


🏁 Script executed:

#!/bin/bash
# Find the implementation of getErrorMessageShared
fd -e ts | xargs grep -l "export.*getErrorMessageShared\|function getErrorMessageShared" | head -3

Repository: AutoMaker-Org/automaker

Length of output: 190


🏁 Script executed:

#!/bin/bash
# Find the actual implementation of getErrorMessage
cat apps/server/src/routes/common.ts | grep -A 20 "export.*getErrorMessage\|export function getErrorMessage"

Repository: AutoMaker-Org/automaker

Length of output: 472


Consider improving error message guidance for git configuration.

Git requires user.name and user.email to be configured before committing, but the current error message doesn't mention this requirement. When git commit --allow-empty fails due to missing configuration, users will see only the underlying git error (already included via reason).

Since all test setups explicitly configure git before operations, production environments should ensure this is set up. The error message could proactively guide users:

     } catch (error) {
       const reason = getErrorMessageShared(error);
       throw new Error(
-        `Failed to create initial git commit. Please commit manually and retry. ${reason}`
+        `Failed to create initial git commit. Ensure git user.name and user.email are configured, then commit manually and retry. ${reason}`
       );
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export async function ensureInitialCommit(repoPath: string): Promise<boolean> {
try {
await execAsync("git rev-parse --verify HEAD", { cwd: repoPath });
return false;
} catch {
try {
await execAsync(
`git commit --allow-empty -m "${AUTOMAKER_INITIAL_COMMIT_MESSAGE}"`,
{ cwd: repoPath }
);
logger.info(
`[Worktree] Created initial empty commit to enable worktrees in ${repoPath}`
);
return true;
} catch (error) {
const reason = getErrorMessageShared(error);
throw new Error(
`Failed to create initial git commit. Please commit manually and retry. ${reason}`
);
}
}
}
export async function ensureInitialCommit(repoPath: string): Promise<boolean> {
try {
await execAsync("git rev-parse --verify HEAD", { cwd: repoPath });
return false;
} catch {
try {
await execAsync(
`git commit --allow-empty -m "${AUTOMAKER_INITIAL_COMMIT_MESSAGE}"`,
{ cwd: repoPath }
);
logger.info(
`[Worktree] Created initial empty commit to enable worktrees in ${repoPath}`
);
return true;
} catch (error) {
const reason = getErrorMessageShared(error);
throw new Error(
`Failed to create initial git commit. Ensure git user.name and user.email are configured, then commit manually and retry. ${reason}`
);
}
}
}
🤖 Prompt for AI Agents
In apps/server/src/routes/worktree/common.ts around lines 84 to 105, the error
thrown when creating the initial empty commit lacks proactive guidance about git
user configuration; update the thrown Error to include the original reason plus
a brief actionable suggestion to set git user.name and user.email (e.g. "git
config --global user.name 'Your Name' && git config --global user.email
'you@example.com'") or to configure them in the repo, so users get clear next
steps when commits fail due to missing git config.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants