mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-02-03 21:03:08 +00:00
feat(board-view): enhance feature and plan dialogs with worktree branch settings
- Added WorktreeSettingsDialog and PlanSettingsDialog components to manage worktree branch settings. - Integrated new settings into BoardHeader for toggling worktree branch usage in feature creation. - Updated AddFeatureDialog to utilize selected worktree branch for custom mode. - Introduced new state management in app-store for handling worktree branch preferences. These changes improve user control over feature creation workflows by allowing branch selection based on the current worktree context.
This commit is contained in:
@@ -101,6 +101,8 @@ export function BoardView() {
|
|||||||
useWorktrees,
|
useWorktrees,
|
||||||
enableDependencyBlocking,
|
enableDependencyBlocking,
|
||||||
skipVerificationInAutoMode,
|
skipVerificationInAutoMode,
|
||||||
|
planUseSelectedWorktreeBranch,
|
||||||
|
addFeatureUseSelectedWorktreeBranch,
|
||||||
isPrimaryWorktreeBranch,
|
isPrimaryWorktreeBranch,
|
||||||
getPrimaryWorktreeBranch,
|
getPrimaryWorktreeBranch,
|
||||||
setPipelineConfig,
|
setPipelineConfig,
|
||||||
@@ -1370,6 +1372,14 @@ export function BoardView() {
|
|||||||
isMaximized={isMaximized}
|
isMaximized={isMaximized}
|
||||||
parentFeature={spawnParentFeature}
|
parentFeature={spawnParentFeature}
|
||||||
allFeatures={hookFeatures}
|
allFeatures={hookFeatures}
|
||||||
|
// When setting is enabled and a non-main worktree is selected, pass its branch to default to 'custom' work mode
|
||||||
|
selectedNonMainWorktreeBranch={
|
||||||
|
addFeatureUseSelectedWorktreeBranch && currentWorktreePath !== null
|
||||||
|
? currentWorktreeBranch || undefined
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
// When the worktree setting is disabled, force 'current' branch mode
|
||||||
|
forceCurrentBranchMode={!addFeatureUseSelectedWorktreeBranch}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Edit Feature Dialog */}
|
{/* Edit Feature Dialog */}
|
||||||
@@ -1449,7 +1459,7 @@ export function BoardView() {
|
|||||||
setPendingPlanResult={setPendingBacklogPlan}
|
setPendingPlanResult={setPendingBacklogPlan}
|
||||||
isGeneratingPlan={isGeneratingPlan}
|
isGeneratingPlan={isGeneratingPlan}
|
||||||
setIsGeneratingPlan={setIsGeneratingPlan}
|
setIsGeneratingPlan={setIsGeneratingPlan}
|
||||||
currentBranch={selectedWorktreeBranch}
|
currentBranch={planUseSelectedWorktreeBranch ? selectedWorktreeBranch : undefined}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Plan Approval Dialog */}
|
{/* Plan Approval Dialog */}
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import { UsagePopover } from '@/components/usage-popover';
|
|||||||
import { useAppStore } from '@/store/app-store';
|
import { useAppStore } from '@/store/app-store';
|
||||||
import { useSetupStore } from '@/store/setup-store';
|
import { useSetupStore } from '@/store/setup-store';
|
||||||
import { AutoModeSettingsDialog } from './dialogs/auto-mode-settings-dialog';
|
import { AutoModeSettingsDialog } from './dialogs/auto-mode-settings-dialog';
|
||||||
|
import { WorktreeSettingsDialog } from './dialogs/worktree-settings-dialog';
|
||||||
|
import { PlanSettingsDialog } from './dialogs/plan-settings-dialog';
|
||||||
import { getHttpApiClient } from '@/lib/http-api-client';
|
import { getHttpApiClient } from '@/lib/http-api-client';
|
||||||
import { BoardSearchBar } from './board-search-bar';
|
import { BoardSearchBar } from './board-search-bar';
|
||||||
import { BoardControls } from './board-controls';
|
import { BoardControls } from './board-controls';
|
||||||
@@ -55,10 +57,22 @@ export function BoardHeader({
|
|||||||
completedCount,
|
completedCount,
|
||||||
}: BoardHeaderProps) {
|
}: BoardHeaderProps) {
|
||||||
const [showAutoModeSettings, setShowAutoModeSettings] = useState(false);
|
const [showAutoModeSettings, setShowAutoModeSettings] = useState(false);
|
||||||
|
const [showWorktreeSettings, setShowWorktreeSettings] = useState(false);
|
||||||
|
const [showPlanSettings, setShowPlanSettings] = useState(false);
|
||||||
const apiKeys = useAppStore((state) => state.apiKeys);
|
const apiKeys = useAppStore((state) => state.apiKeys);
|
||||||
const claudeAuthStatus = useSetupStore((state) => state.claudeAuthStatus);
|
const claudeAuthStatus = useSetupStore((state) => state.claudeAuthStatus);
|
||||||
const skipVerificationInAutoMode = useAppStore((state) => state.skipVerificationInAutoMode);
|
const skipVerificationInAutoMode = useAppStore((state) => state.skipVerificationInAutoMode);
|
||||||
const setSkipVerificationInAutoMode = useAppStore((state) => state.setSkipVerificationInAutoMode);
|
const setSkipVerificationInAutoMode = useAppStore((state) => state.setSkipVerificationInAutoMode);
|
||||||
|
const planUseSelectedWorktreeBranch = useAppStore((state) => state.planUseSelectedWorktreeBranch);
|
||||||
|
const setPlanUseSelectedWorktreeBranch = useAppStore(
|
||||||
|
(state) => state.setPlanUseSelectedWorktreeBranch
|
||||||
|
);
|
||||||
|
const addFeatureUseSelectedWorktreeBranch = useAppStore(
|
||||||
|
(state) => state.addFeatureUseSelectedWorktreeBranch
|
||||||
|
);
|
||||||
|
const setAddFeatureUseSelectedWorktreeBranch = useAppStore(
|
||||||
|
(state) => state.setAddFeatureUseSelectedWorktreeBranch
|
||||||
|
);
|
||||||
const codexAuthStatus = useSetupStore((state) => state.codexAuthStatus);
|
const codexAuthStatus = useSetupStore((state) => state.codexAuthStatus);
|
||||||
|
|
||||||
// Worktree panel visibility (per-project)
|
// Worktree panel visibility (per-project)
|
||||||
@@ -132,9 +146,25 @@ export function BoardHeader({
|
|||||||
onCheckedChange={handleWorktreePanelToggle}
|
onCheckedChange={handleWorktreePanelToggle}
|
||||||
data-testid="worktrees-toggle"
|
data-testid="worktrees-toggle"
|
||||||
/>
|
/>
|
||||||
|
<button
|
||||||
|
onClick={() => setShowWorktreeSettings(true)}
|
||||||
|
className="p-1 rounded hover:bg-accent/50 transition-colors"
|
||||||
|
title="Worktree Settings"
|
||||||
|
data-testid="worktree-settings-button"
|
||||||
|
>
|
||||||
|
<Settings2 className="w-4 h-4 text-muted-foreground" />
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* Worktree Settings Dialog */}
|
||||||
|
<WorktreeSettingsDialog
|
||||||
|
open={showWorktreeSettings}
|
||||||
|
onOpenChange={setShowWorktreeSettings}
|
||||||
|
addFeatureUseSelectedWorktreeBranch={addFeatureUseSelectedWorktreeBranch}
|
||||||
|
onAddFeatureUseSelectedWorktreeBranchChange={setAddFeatureUseSelectedWorktreeBranch}
|
||||||
|
/>
|
||||||
|
|
||||||
{/* Concurrency Control - only show after mount to prevent hydration issues */}
|
{/* Concurrency Control - only show after mount to prevent hydration issues */}
|
||||||
{isMounted && (
|
{isMounted && (
|
||||||
<Popover>
|
<Popover>
|
||||||
@@ -209,15 +239,33 @@ export function BoardHeader({
|
|||||||
onSkipVerificationChange={setSkipVerificationInAutoMode}
|
onSkipVerificationChange={setSkipVerificationInAutoMode}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Button
|
{/* Plan Button with Settings */}
|
||||||
size="sm"
|
<div className={controlContainerClass} data-testid="plan-button-container">
|
||||||
variant="outline"
|
<button
|
||||||
onClick={onOpenPlanDialog}
|
onClick={onOpenPlanDialog}
|
||||||
data-testid="plan-backlog-button"
|
className="flex items-center gap-1.5 hover:text-foreground transition-colors"
|
||||||
>
|
data-testid="plan-backlog-button"
|
||||||
<Wand2 className="w-4 h-4 mr-2" />
|
>
|
||||||
Plan
|
<Wand2 className="w-4 h-4 text-muted-foreground" />
|
||||||
</Button>
|
<span className="text-sm font-medium">Plan</span>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => setShowPlanSettings(true)}
|
||||||
|
className="p-1 rounded hover:bg-accent/50 transition-colors"
|
||||||
|
title="Plan Settings"
|
||||||
|
data-testid="plan-settings-button"
|
||||||
|
>
|
||||||
|
<Settings2 className="w-4 h-4 text-muted-foreground" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Plan Settings Dialog */}
|
||||||
|
<PlanSettingsDialog
|
||||||
|
open={showPlanSettings}
|
||||||
|
onOpenChange={setShowPlanSettings}
|
||||||
|
planUseSelectedWorktreeBranch={planUseSelectedWorktreeBranch}
|
||||||
|
onPlanUseSelectedWorktreeBranchChange={setPlanUseSelectedWorktreeBranch}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -56,6 +56,32 @@ import {
|
|||||||
|
|
||||||
const logger = createLogger('AddFeatureDialog');
|
const logger = createLogger('AddFeatureDialog');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines the default work mode based on global settings and current worktree selection.
|
||||||
|
*
|
||||||
|
* Priority:
|
||||||
|
* 1. If forceCurrentBranchMode is true, always defaults to 'current' (work on current branch)
|
||||||
|
* 2. If a non-main worktree is selected in the board header, defaults to 'custom' (use that branch)
|
||||||
|
* 3. If useWorktrees global setting is enabled, defaults to 'auto' (automatic worktree creation)
|
||||||
|
* 4. Otherwise, defaults to 'current' (work on current branch without isolation)
|
||||||
|
*/
|
||||||
|
const getDefaultWorkMode = (
|
||||||
|
useWorktrees: boolean,
|
||||||
|
selectedNonMainWorktreeBranch?: string,
|
||||||
|
forceCurrentBranchMode?: boolean
|
||||||
|
): WorkMode => {
|
||||||
|
// If force current branch mode is enabled (worktree setting is off), always use 'current'
|
||||||
|
if (forceCurrentBranchMode) {
|
||||||
|
return 'current';
|
||||||
|
}
|
||||||
|
// If a non-main worktree is selected, default to 'custom' mode with that branch
|
||||||
|
if (selectedNonMainWorktreeBranch) {
|
||||||
|
return 'custom';
|
||||||
|
}
|
||||||
|
// Otherwise, respect the global worktree setting
|
||||||
|
return useWorktrees ? 'auto' : 'current';
|
||||||
|
};
|
||||||
|
|
||||||
type FeatureData = {
|
type FeatureData = {
|
||||||
title: string;
|
title: string;
|
||||||
category: string;
|
category: string;
|
||||||
@@ -89,6 +115,16 @@ interface AddFeatureDialogProps {
|
|||||||
isMaximized: boolean;
|
isMaximized: boolean;
|
||||||
parentFeature?: Feature | null;
|
parentFeature?: Feature | null;
|
||||||
allFeatures?: Feature[];
|
allFeatures?: Feature[];
|
||||||
|
/**
|
||||||
|
* When a non-main worktree is selected in the board header, this will be set to that worktree's branch.
|
||||||
|
* When set, the dialog will default to 'custom' work mode with this branch pre-filled.
|
||||||
|
*/
|
||||||
|
selectedNonMainWorktreeBranch?: string;
|
||||||
|
/**
|
||||||
|
* When true, forces the dialog to default to 'current' work mode (work on current branch).
|
||||||
|
* This is used when the "Use selected worktree branch" setting is disabled.
|
||||||
|
*/
|
||||||
|
forceCurrentBranchMode?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -112,6 +148,8 @@ export function AddFeatureDialog({
|
|||||||
isMaximized,
|
isMaximized,
|
||||||
parentFeature = null,
|
parentFeature = null,
|
||||||
allFeatures = [],
|
allFeatures = [],
|
||||||
|
selectedNonMainWorktreeBranch,
|
||||||
|
forceCurrentBranchMode,
|
||||||
}: AddFeatureDialogProps) {
|
}: AddFeatureDialogProps) {
|
||||||
const isSpawnMode = !!parentFeature;
|
const isSpawnMode = !!parentFeature;
|
||||||
const [workMode, setWorkMode] = useState<WorkMode>('current');
|
const [workMode, setWorkMode] = useState<WorkMode>('current');
|
||||||
@@ -149,7 +187,7 @@ export function AddFeatureDialog({
|
|||||||
const [selectedAncestorIds, setSelectedAncestorIds] = useState<Set<string>>(new Set());
|
const [selectedAncestorIds, setSelectedAncestorIds] = useState<Set<string>>(new Set());
|
||||||
|
|
||||||
// Get defaults from store
|
// Get defaults from store
|
||||||
const { defaultPlanningMode, defaultRequirePlanApproval } = useAppStore();
|
const { defaultPlanningMode, defaultRequirePlanApproval, useWorktrees } = useAppStore();
|
||||||
|
|
||||||
// Track previous open state to detect when dialog opens
|
// Track previous open state to detect when dialog opens
|
||||||
const wasOpenRef = useRef(false);
|
const wasOpenRef = useRef(false);
|
||||||
@@ -161,8 +199,12 @@ export function AddFeatureDialog({
|
|||||||
|
|
||||||
if (justOpened) {
|
if (justOpened) {
|
||||||
setSkipTests(defaultSkipTests);
|
setSkipTests(defaultSkipTests);
|
||||||
setBranchName(defaultBranch || '');
|
// When a non-main worktree is selected, use its branch name for custom mode
|
||||||
setWorkMode('current');
|
// Otherwise, use the default branch
|
||||||
|
setBranchName(selectedNonMainWorktreeBranch || defaultBranch || '');
|
||||||
|
setWorkMode(
|
||||||
|
getDefaultWorkMode(useWorktrees, selectedNonMainWorktreeBranch, forceCurrentBranchMode)
|
||||||
|
);
|
||||||
setPlanningMode(defaultPlanningMode);
|
setPlanningMode(defaultPlanningMode);
|
||||||
setRequirePlanApproval(defaultRequirePlanApproval);
|
setRequirePlanApproval(defaultRequirePlanApproval);
|
||||||
setModelEntry({ model: 'opus' });
|
setModelEntry({ model: 'opus' });
|
||||||
@@ -186,6 +228,9 @@ export function AddFeatureDialog({
|
|||||||
defaultBranch,
|
defaultBranch,
|
||||||
defaultPlanningMode,
|
defaultPlanningMode,
|
||||||
defaultRequirePlanApproval,
|
defaultRequirePlanApproval,
|
||||||
|
useWorktrees,
|
||||||
|
selectedNonMainWorktreeBranch,
|
||||||
|
forceCurrentBranchMode,
|
||||||
parentFeature,
|
parentFeature,
|
||||||
allFeatures,
|
allFeatures,
|
||||||
]);
|
]);
|
||||||
@@ -270,10 +315,13 @@ export function AddFeatureDialog({
|
|||||||
setImagePaths([]);
|
setImagePaths([]);
|
||||||
setTextFilePaths([]);
|
setTextFilePaths([]);
|
||||||
setSkipTests(defaultSkipTests);
|
setSkipTests(defaultSkipTests);
|
||||||
setBranchName('');
|
// When a non-main worktree is selected, use its branch name for custom mode
|
||||||
|
setBranchName(selectedNonMainWorktreeBranch || '');
|
||||||
setPriority(2);
|
setPriority(2);
|
||||||
setModelEntry({ model: 'opus' });
|
setModelEntry({ model: 'opus' });
|
||||||
setWorkMode('current');
|
setWorkMode(
|
||||||
|
getDefaultWorkMode(useWorktrees, selectedNonMainWorktreeBranch, forceCurrentBranchMode)
|
||||||
|
);
|
||||||
setPlanningMode(defaultPlanningMode);
|
setPlanningMode(defaultPlanningMode);
|
||||||
setRequirePlanApproval(defaultRequirePlanApproval);
|
setRequirePlanApproval(defaultRequirePlanApproval);
|
||||||
setPreviewMap(new Map());
|
setPreviewMap(new Map());
|
||||||
|
|||||||
@@ -0,0 +1,67 @@
|
|||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogDescription,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
} from '@/components/ui/dialog';
|
||||||
|
import { Label } from '@/components/ui/label';
|
||||||
|
import { Switch } from '@/components/ui/switch';
|
||||||
|
import { GitBranch, Settings2 } from 'lucide-react';
|
||||||
|
|
||||||
|
interface PlanSettingsDialogProps {
|
||||||
|
open: boolean;
|
||||||
|
onOpenChange: (open: boolean) => void;
|
||||||
|
planUseSelectedWorktreeBranch: boolean;
|
||||||
|
onPlanUseSelectedWorktreeBranchChange: (value: boolean) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function PlanSettingsDialog({
|
||||||
|
open,
|
||||||
|
onOpenChange,
|
||||||
|
planUseSelectedWorktreeBranch,
|
||||||
|
onPlanUseSelectedWorktreeBranchChange,
|
||||||
|
}: PlanSettingsDialogProps) {
|
||||||
|
return (
|
||||||
|
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||||
|
<DialogContent className="sm:max-w-md" data-testid="plan-settings-dialog">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle className="flex items-center gap-2">
|
||||||
|
<Settings2 className="w-5 h-5" />
|
||||||
|
Plan Settings
|
||||||
|
</DialogTitle>
|
||||||
|
<DialogDescription>
|
||||||
|
Configure how the Plan feature creates and organizes new features.
|
||||||
|
</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
|
||||||
|
<div className="space-y-4 py-4">
|
||||||
|
{/* Use Selected Worktree Branch Setting */}
|
||||||
|
<div className="flex items-start space-x-3 p-3 rounded-lg bg-secondary/50">
|
||||||
|
<div className="flex-1 space-y-1">
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<Label
|
||||||
|
htmlFor="plan-worktree-branch-toggle"
|
||||||
|
className="text-sm font-medium cursor-pointer flex items-center gap-2"
|
||||||
|
>
|
||||||
|
<GitBranch className="w-4 h-4 text-brand-500" />
|
||||||
|
Use selected worktree branch
|
||||||
|
</Label>
|
||||||
|
<Switch
|
||||||
|
id="plan-worktree-branch-toggle"
|
||||||
|
checked={planUseSelectedWorktreeBranch}
|
||||||
|
onCheckedChange={onPlanUseSelectedWorktreeBranchChange}
|
||||||
|
data-testid="plan-worktree-branch-toggle"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<p className="text-xs text-muted-foreground leading-relaxed">
|
||||||
|
When enabled, features created via the Plan dialog will be assigned to the currently
|
||||||
|
selected worktree branch. When disabled, features will be added to the main branch.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogDescription,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
} from '@/components/ui/dialog';
|
||||||
|
import { Label } from '@/components/ui/label';
|
||||||
|
import { Switch } from '@/components/ui/switch';
|
||||||
|
import { GitBranch, Settings2 } from 'lucide-react';
|
||||||
|
|
||||||
|
interface WorktreeSettingsDialogProps {
|
||||||
|
open: boolean;
|
||||||
|
onOpenChange: (open: boolean) => void;
|
||||||
|
addFeatureUseSelectedWorktreeBranch: boolean;
|
||||||
|
onAddFeatureUseSelectedWorktreeBranchChange: (value: boolean) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function WorktreeSettingsDialog({
|
||||||
|
open,
|
||||||
|
onOpenChange,
|
||||||
|
addFeatureUseSelectedWorktreeBranch,
|
||||||
|
onAddFeatureUseSelectedWorktreeBranchChange,
|
||||||
|
}: WorktreeSettingsDialogProps) {
|
||||||
|
return (
|
||||||
|
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||||
|
<DialogContent className="sm:max-w-md" data-testid="worktree-settings-dialog">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle className="flex items-center gap-2">
|
||||||
|
<Settings2 className="w-5 h-5" />
|
||||||
|
Worktree Settings
|
||||||
|
</DialogTitle>
|
||||||
|
<DialogDescription>
|
||||||
|
Configure how worktrees affect feature creation and organization.
|
||||||
|
</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
|
||||||
|
<div className="space-y-4 py-4">
|
||||||
|
{/* Use Selected Worktree Branch Setting */}
|
||||||
|
<div className="flex items-start space-x-3 p-3 rounded-lg bg-secondary/50">
|
||||||
|
<div className="flex-1 space-y-1">
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<Label
|
||||||
|
htmlFor="worktree-branch-toggle"
|
||||||
|
className="text-sm font-medium cursor-pointer flex items-center gap-2"
|
||||||
|
>
|
||||||
|
<GitBranch className="w-4 h-4 text-brand-500" />
|
||||||
|
Use selected worktree branch
|
||||||
|
</Label>
|
||||||
|
<Switch
|
||||||
|
id="worktree-branch-toggle"
|
||||||
|
checked={addFeatureUseSelectedWorktreeBranch}
|
||||||
|
onCheckedChange={onAddFeatureUseSelectedWorktreeBranchChange}
|
||||||
|
data-testid="worktree-branch-toggle"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<p className="text-xs text-muted-foreground leading-relaxed">
|
||||||
|
When enabled, the Add Feature dialog will default to custom branch mode with the
|
||||||
|
currently selected worktree branch pre-filled.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -530,6 +530,8 @@ export interface AppState {
|
|||||||
defaultSkipTests: boolean; // Default value for skip tests when creating new features
|
defaultSkipTests: boolean; // Default value for skip tests when creating new features
|
||||||
enableDependencyBlocking: boolean; // When true, show blocked badges and warnings for features with incomplete dependencies (default: true)
|
enableDependencyBlocking: boolean; // When true, show blocked badges and warnings for features with incomplete dependencies (default: true)
|
||||||
skipVerificationInAutoMode: boolean; // When true, auto-mode grabs features even if dependencies are not verified (only checks they're not running)
|
skipVerificationInAutoMode: boolean; // When true, auto-mode grabs features even if dependencies are not verified (only checks they're not running)
|
||||||
|
planUseSelectedWorktreeBranch: boolean; // When true, Plan dialog creates features on the currently selected worktree branch
|
||||||
|
addFeatureUseSelectedWorktreeBranch: boolean; // When true, Add Feature dialog defaults to custom mode with selected worktree branch
|
||||||
|
|
||||||
// Worktree Settings
|
// Worktree Settings
|
||||||
useWorktrees: boolean; // Whether to use git worktree isolation for features (default: true)
|
useWorktrees: boolean; // Whether to use git worktree isolation for features (default: true)
|
||||||
@@ -913,6 +915,8 @@ export interface AppActions {
|
|||||||
setDefaultSkipTests: (skip: boolean) => void;
|
setDefaultSkipTests: (skip: boolean) => void;
|
||||||
setEnableDependencyBlocking: (enabled: boolean) => void;
|
setEnableDependencyBlocking: (enabled: boolean) => void;
|
||||||
setSkipVerificationInAutoMode: (enabled: boolean) => Promise<void>;
|
setSkipVerificationInAutoMode: (enabled: boolean) => Promise<void>;
|
||||||
|
setPlanUseSelectedWorktreeBranch: (enabled: boolean) => Promise<void>;
|
||||||
|
setAddFeatureUseSelectedWorktreeBranch: (enabled: boolean) => Promise<void>;
|
||||||
|
|
||||||
// Worktree Settings actions
|
// Worktree Settings actions
|
||||||
setUseWorktrees: (enabled: boolean) => void;
|
setUseWorktrees: (enabled: boolean) => void;
|
||||||
@@ -1191,6 +1195,8 @@ const initialState: AppState = {
|
|||||||
defaultSkipTests: true, // Default to manual verification (tests disabled)
|
defaultSkipTests: true, // Default to manual verification (tests disabled)
|
||||||
enableDependencyBlocking: true, // Default to enabled (show dependency blocking UI)
|
enableDependencyBlocking: true, // Default to enabled (show dependency blocking UI)
|
||||||
skipVerificationInAutoMode: false, // Default to disabled (require dependencies to be verified)
|
skipVerificationInAutoMode: false, // Default to disabled (require dependencies to be verified)
|
||||||
|
planUseSelectedWorktreeBranch: true, // Default to enabled (Plan creates features on selected worktree branch)
|
||||||
|
addFeatureUseSelectedWorktreeBranch: false, // Default to disabled (Add Feature uses normal defaults)
|
||||||
useWorktrees: true, // Default to enabled (git worktree isolation)
|
useWorktrees: true, // Default to enabled (git worktree isolation)
|
||||||
currentWorktreeByProject: {},
|
currentWorktreeByProject: {},
|
||||||
worktreesByProject: {},
|
worktreesByProject: {},
|
||||||
@@ -1816,6 +1822,18 @@ export const useAppStore = create<AppState & AppActions>()((set, get) => ({
|
|||||||
const { syncSettingsToServer } = await import('@/hooks/use-settings-migration');
|
const { syncSettingsToServer } = await import('@/hooks/use-settings-migration');
|
||||||
await syncSettingsToServer();
|
await syncSettingsToServer();
|
||||||
},
|
},
|
||||||
|
setPlanUseSelectedWorktreeBranch: async (enabled) => {
|
||||||
|
set({ planUseSelectedWorktreeBranch: enabled });
|
||||||
|
// Sync to server settings file
|
||||||
|
const { syncSettingsToServer } = await import('@/hooks/use-settings-migration');
|
||||||
|
await syncSettingsToServer();
|
||||||
|
},
|
||||||
|
setAddFeatureUseSelectedWorktreeBranch: async (enabled) => {
|
||||||
|
set({ addFeatureUseSelectedWorktreeBranch: enabled });
|
||||||
|
// Sync to server settings file
|
||||||
|
const { syncSettingsToServer } = await import('@/hooks/use-settings-migration');
|
||||||
|
await syncSettingsToServer();
|
||||||
|
},
|
||||||
|
|
||||||
// Worktree Settings actions
|
// Worktree Settings actions
|
||||||
setUseWorktrees: (enabled) => set({ useWorktrees: enabled }),
|
setUseWorktrees: (enabled) => set({ useWorktrees: enabled }),
|
||||||
|
|||||||
Reference in New Issue
Block a user