merge: sync with latest v0.9.0rc changes

This commit is contained in:
Kacper
2026-01-09 22:27:06 +01:00
10 changed files with 287 additions and 93 deletions

View File

@@ -615,7 +615,8 @@ export class SettingsService {
appState.skipVerificationInAutoMode !== undefined appState.skipVerificationInAutoMode !== undefined
? (appState.skipVerificationInAutoMode as boolean) ? (appState.skipVerificationInAutoMode as boolean)
: false, : false,
useWorktrees: (appState.useWorktrees as boolean) || false, useWorktrees:
appState.useWorktrees !== undefined ? (appState.useWorktrees as boolean) : true,
showProfilesOnly: (appState.showProfilesOnly as boolean) || false, showProfilesOnly: (appState.showProfilesOnly as boolean) || false,
defaultPlanningMode: defaultPlanningMode:
(appState.defaultPlanningMode as GlobalSettings['defaultPlanningMode']) || 'skip', (appState.defaultPlanningMode as GlobalSettings['defaultPlanningMode']) || 'skip',

View File

@@ -1,5 +1,5 @@
// @ts-nocheck // @ts-nocheck
import { useState, useEffect } from 'react'; import { useState, useEffect, useRef } from 'react';
import { createLogger } from '@automaker/utils/logger'; import { createLogger } from '@automaker/utils/logger';
import { import {
Dialog, Dialog,
@@ -46,11 +46,12 @@ import {
import { import {
TestingTabContent, TestingTabContent,
PrioritySelector, PrioritySelector,
BranchSelector, WorkModeSelector,
PlanningModeSelect, PlanningModeSelect,
AncestorContextSection, AncestorContextSection,
ProfileTypeahead, ProfileTypeahead,
} from '../shared'; } from '../shared';
import type { WorkMode } from '../shared';
import { PhaseModelSelector } from '@/components/views/settings-view/model-defaults/phase-model-selector'; import { PhaseModelSelector } from '@/components/views/settings-view/model-defaults/phase-model-selector';
import { ModelOverrideTrigger, useModelOverride } from '@/components/shared'; import { ModelOverrideTrigger, useModelOverride } from '@/components/shared';
import { import {
@@ -84,6 +85,7 @@ type FeatureData = {
planningMode: PlanningMode; planningMode: PlanningMode;
requirePlanApproval: boolean; requirePlanApproval: boolean;
dependencies?: string[]; dependencies?: string[];
workMode: WorkMode;
}; };
interface AddFeatureDialogProps { interface AddFeatureDialogProps {
@@ -123,7 +125,7 @@ export function AddFeatureDialog({
}: AddFeatureDialogProps) { }: AddFeatureDialogProps) {
const isSpawnMode = !!parentFeature; const isSpawnMode = !!parentFeature;
const navigate = useNavigate(); const navigate = useNavigate();
const [useCurrentBranch, setUseCurrentBranch] = useState(true); const [workMode, setWorkMode] = useState<WorkMode>('current');
// Form state // Form state
const [title, setTitle] = useState(''); const [title, setTitle] = useState('');
@@ -161,22 +163,27 @@ 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, defaultAIProfileId, useWorktrees } = const { defaultPlanningMode, defaultRequirePlanApproval, defaultAIProfileId } = useAppStore();
useAppStore();
// Enhancement model override // Enhancement model override
const enhancementOverride = useModelOverride({ phase: 'enhancementModel' }); const enhancementOverride = useModelOverride({ phase: 'enhancementModel' });
// Sync defaults when dialog opens // Track previous open state to detect when dialog opens
const wasOpenRef = useRef(false);
// Sync defaults only when dialog opens (transitions from closed to open)
useEffect(() => { useEffect(() => {
if (open) { const justOpened = open && !wasOpenRef.current;
wasOpenRef.current = open;
if (justOpened) {
const defaultProfile = defaultAIProfileId const defaultProfile = defaultAIProfileId
? aiProfiles.find((p) => p.id === defaultAIProfileId) ? aiProfiles.find((p) => p.id === defaultAIProfileId)
: null; : null;
setSkipTests(defaultSkipTests); setSkipTests(defaultSkipTests);
setBranchName(defaultBranch || ''); setBranchName(defaultBranch || '');
setUseCurrentBranch(true); setWorkMode('current');
setPlanningMode(defaultPlanningMode); setPlanningMode(defaultPlanningMode);
setRequirePlanApproval(defaultRequirePlanApproval); setRequirePlanApproval(defaultRequirePlanApproval);
@@ -248,7 +255,7 @@ export function AddFeatureDialog({
return null; return null;
} }
if (useWorktrees && !useCurrentBranch && !branchName.trim()) { if (workMode === 'custom' && !branchName.trim()) {
toast.error('Please select a branch name'); toast.error('Please select a branch name');
return null; return null;
} }
@@ -262,7 +269,10 @@ export function AddFeatureDialog({
? modelEntry.reasoningEffort || 'none' ? modelEntry.reasoningEffort || 'none'
: 'none'; : 'none';
const finalBranchName = useCurrentBranch ? currentBranch || '' : branchName || ''; // For 'current' mode, use empty string (work on current branch)
// For 'auto' mode, use empty string (will be auto-generated in use-board-actions)
// For 'custom' mode, use the specified branch name
const finalBranchName = workMode === 'custom' ? branchName || '' : '';
// Build final description with ancestor context in spawn mode // Build final description with ancestor context in spawn mode
let finalDescription = description; let finalDescription = description;
@@ -303,6 +313,7 @@ export function AddFeatureDialog({
planningMode, planningMode,
requirePlanApproval, requirePlanApproval,
dependencies: isSpawnMode && parentFeature ? [parentFeature.id] : undefined, dependencies: isSpawnMode && parentFeature ? [parentFeature.id] : undefined,
workMode,
}; };
}; };
@@ -318,7 +329,7 @@ export function AddFeatureDialog({
setPriority(2); setPriority(2);
setSelectedProfileId(undefined); setSelectedProfileId(undefined);
setModelEntry({ model: 'opus' }); setModelEntry({ model: 'opus' });
setUseCurrentBranch(true); setWorkMode('current');
setPlanningMode(defaultPlanningMode); setPlanningMode(defaultPlanningMode);
setRequirePlanApproval(defaultRequirePlanApproval); setRequirePlanApproval(defaultRequirePlanApproval);
setPreviewMap(new Map()); setPreviewMap(new Map());
@@ -643,21 +654,19 @@ export function AddFeatureDialog({
</div> </div>
</div> </div>
{/* Branch Selector */} {/* Work Mode Selector */}
{useWorktrees && ( <div className="pt-2">
<div className="pt-2"> <WorkModeSelector
<BranchSelector workMode={workMode}
useCurrentBranch={useCurrentBranch} onWorkModeChange={setWorkMode}
onUseCurrentBranchChange={setUseCurrentBranch} branchName={branchName}
branchName={branchName} onBranchNameChange={setBranchName}
onBranchNameChange={setBranchName} branchSuggestions={branchSuggestions}
branchSuggestions={branchSuggestions} branchCardCounts={branchCardCounts}
branchCardCounts={branchCardCounts} currentBranch={currentBranch}
currentBranch={currentBranch} testIdPrefix="feature-work-mode"
testIdPrefix="feature" />
/> </div>
</div>
)}
</div> </div>
</div> </div>
@@ -670,7 +679,7 @@ export function AddFeatureDialog({
onClick={handleAddAndStart} onClick={handleAddAndStart}
variant="secondary" variant="secondary"
data-testid="confirm-add-and-start-feature" data-testid="confirm-add-and-start-feature"
disabled={useWorktrees && !useCurrentBranch && !branchName.trim()} disabled={workMode === 'custom' && !branchName.trim()}
> >
<Play className="w-4 h-4 mr-2" /> <Play className="w-4 h-4 mr-2" />
Make Make
@@ -681,7 +690,7 @@ export function AddFeatureDialog({
hotkey={{ key: 'Enter', cmdCtrl: true }} hotkey={{ key: 'Enter', cmdCtrl: true }}
hotkeyActive={open} hotkeyActive={open}
data-testid="confirm-add-feature" data-testid="confirm-add-feature"
disabled={useWorktrees && !useCurrentBranch && !branchName.trim()} disabled={workMode === 'custom' && !branchName.trim()}
> >
{isSpawnMode ? 'Spawn Task' : 'Add Feature'} {isSpawnMode ? 'Spawn Task' : 'Add Feature'}
</HotkeyButton> </HotkeyButton>

View File

@@ -46,10 +46,11 @@ import type { ReasoningEffort, PhaseModelEntry, DescriptionHistoryEntry } from '
import { import {
TestingTabContent, TestingTabContent,
PrioritySelector, PrioritySelector,
BranchSelector, WorkModeSelector,
PlanningModeSelect, PlanningModeSelect,
ProfileTypeahead, ProfileTypeahead,
} from '../shared'; } from '../shared';
import type { WorkMode } from '../shared';
import { PhaseModelSelector } from '@/components/views/settings-view/model-defaults/phase-model-selector'; import { PhaseModelSelector } from '@/components/views/settings-view/model-defaults/phase-model-selector';
import { ModelOverrideTrigger, useModelOverride } from '@/components/shared'; import { ModelOverrideTrigger, useModelOverride } from '@/components/shared';
import { import {
@@ -118,9 +119,11 @@ export function EditFeatureDialog({
}: EditFeatureDialogProps) { }: EditFeatureDialogProps) {
const navigate = useNavigate(); const navigate = useNavigate();
const [editingFeature, setEditingFeature] = useState<Feature | null>(feature); const [editingFeature, setEditingFeature] = useState<Feature | null>(feature);
const [useCurrentBranch, setUseCurrentBranch] = useState(() => { // Derive initial workMode from feature's branchName
// If feature has no branchName, default to using current branch const [workMode, setWorkMode] = useState<WorkMode>(() => {
return !feature?.branchName; // If feature has a branchName, it's using 'custom' mode
// Otherwise, it's on 'current' branch (no worktree isolation)
return feature?.branchName ? 'custom' : 'current';
}); });
const [editFeaturePreviewMap, setEditFeaturePreviewMap] = useState<ImagePreviewMap>( const [editFeaturePreviewMap, setEditFeaturePreviewMap] = useState<ImagePreviewMap>(
() => new Map() () => new Map()
@@ -156,9 +159,6 @@ export function EditFeatureDialog({
// Track if history dropdown is open // Track if history dropdown is open
const [showHistory, setShowHistory] = useState(false); const [showHistory, setShowHistory] = useState(false);
// Get worktrees setting from store
const { useWorktrees } = useAppStore();
// Enhancement model override // Enhancement model override
const enhancementOverride = useModelOverride({ phase: 'enhancementModel' }); const enhancementOverride = useModelOverride({ phase: 'enhancementModel' });
@@ -167,8 +167,8 @@ export function EditFeatureDialog({
if (feature) { if (feature) {
setPlanningMode(feature.planningMode ?? 'skip'); setPlanningMode(feature.planningMode ?? 'skip');
setRequirePlanApproval(feature.requirePlanApproval ?? false); setRequirePlanApproval(feature.requirePlanApproval ?? false);
// If feature has no branchName, default to using current branch // Derive workMode from feature's branchName
setUseCurrentBranch(!feature.branchName); setWorkMode(feature.branchName ? 'custom' : 'current');
// Reset history tracking state // Reset history tracking state
setOriginalDescription(feature.description ?? ''); setOriginalDescription(feature.description ?? '');
setDescriptionChangeSource(null); setDescriptionChangeSource(null);
@@ -222,14 +222,9 @@ export function EditFeatureDialog({
const handleUpdate = () => { const handleUpdate = () => {
if (!editingFeature) return; if (!editingFeature) return;
// Validate branch selection when "other branch" is selected and branch selector is enabled // Validate branch selection for custom mode
const isBranchSelectorEnabled = editingFeature.status === 'backlog'; const isBranchSelectorEnabled = editingFeature.status === 'backlog';
if ( if (isBranchSelectorEnabled && workMode === 'custom' && !editingFeature.branchName?.trim()) {
useWorktrees &&
isBranchSelectorEnabled &&
!useCurrentBranch &&
!editingFeature.branchName?.trim()
) {
toast.error('Please select a branch name'); toast.error('Please select a branch name');
return; return;
} }
@@ -242,12 +237,10 @@ export function EditFeatureDialog({
? (modelEntry.reasoningEffort ?? 'none') ? (modelEntry.reasoningEffort ?? 'none')
: 'none'; : 'none';
// Use current branch if toggle is on // For 'current' mode, use empty string (work on current branch)
// If currentBranch is provided (non-primary worktree), use it // For 'auto' mode, use empty string (will be auto-generated in use-board-actions)
// Otherwise (primary worktree), use empty string which means "unassigned" (show only on primary) // For 'custom' mode, use the specified branch name
const finalBranchName = useCurrentBranch const finalBranchName = workMode === 'custom' ? editingFeature.branchName || '' : '';
? currentBranch || ''
: editingFeature.branchName || '';
const updates = { const updates = {
title: editingFeature.title ?? '', title: editingFeature.title ?? '',
@@ -263,6 +256,7 @@ export function EditFeatureDialog({
priority: editingFeature.priority ?? 2, priority: editingFeature.priority ?? 2,
planningMode, planningMode,
requirePlanApproval, requirePlanApproval,
workMode,
}; };
// Determine if description changed and what source to use // Determine if description changed and what source to use
@@ -688,27 +682,25 @@ export function EditFeatureDialog({
</div> </div>
</div> </div>
{/* Branch Selector */} {/* Work Mode Selector */}
{useWorktrees && ( <div className="pt-2">
<div className="pt-2"> <WorkModeSelector
<BranchSelector workMode={workMode}
useCurrentBranch={useCurrentBranch} onWorkModeChange={setWorkMode}
onUseCurrentBranchChange={setUseCurrentBranch} branchName={editingFeature.branchName ?? ''}
branchName={editingFeature.branchName ?? ''} onBranchNameChange={(value) =>
onBranchNameChange={(value) => setEditingFeature({
setEditingFeature({ ...editingFeature,
...editingFeature, branchName: value,
branchName: value, })
}) }
} branchSuggestions={branchSuggestions}
branchSuggestions={branchSuggestions} branchCardCounts={branchCardCounts}
branchCardCounts={branchCardCounts} currentBranch={currentBranch}
currentBranch={currentBranch} disabled={editingFeature.status !== 'backlog'}
disabled={editingFeature.status !== 'backlog'} testIdPrefix="edit-feature-work-mode"
testIdPrefix="edit-feature" />
/> </div>
</div>
)}
</div> </div>
</div> </div>
@@ -731,9 +723,8 @@ export function EditFeatureDialog({
hotkeyActive={!!editingFeature} hotkeyActive={!!editingFeature}
data-testid="confirm-edit-feature" data-testid="confirm-edit-feature"
disabled={ disabled={
useWorktrees &&
editingFeature.status === 'backlog' && editingFeature.status === 'backlog' &&
!useCurrentBranch && workMode === 'custom' &&
!editingFeature.branchName?.trim() !editingFeature.branchName?.trim()
} }
> >

View File

@@ -111,14 +111,32 @@ export function useBoardActions({
planningMode: PlanningMode; planningMode: PlanningMode;
requirePlanApproval: boolean; requirePlanApproval: boolean;
dependencies?: string[]; dependencies?: string[];
workMode?: 'current' | 'auto' | 'custom';
}) => { }) => {
// Empty string means "unassigned" (show only on primary worktree) - convert to undefined const workMode = featureData.workMode || 'current';
// Non-empty string is the actual branch name (for non-primary worktrees)
const finalBranchName = featureData.branchName || undefined;
// If worktrees enabled and a branch is specified, create the worktree now // Determine final branch name based on work mode:
// This ensures the worktree exists before the feature starts // - 'current': No branch name, work on current branch (no worktree)
if (useWorktrees && finalBranchName && currentProject) { // - 'auto': Auto-generate branch name based on current branch
// - '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 current branch and timestamp
const baseBranch = currentWorktreeBranch || 'main';
const timestamp = Date.now();
const randomSuffix = Math.random().toString(36).substring(2, 6);
finalBranchName = `feature/${baseBranch}-${timestamp}-${randomSuffix}`;
} else {
// Custom mode - use provided branch name
finalBranchName = featureData.branchName || undefined;
}
// Create worktree for 'auto' or 'custom' modes when we have a branch name
if ((workMode === 'auto' || workMode === 'custom') && finalBranchName && currentProject) {
try { try {
const api = getElectronAPI(); const api = getElectronAPI();
if (api?.worktree?.create) { if (api?.worktree?.create) {
@@ -207,10 +225,10 @@ export function useBoardActions({
persistFeatureUpdate, persistFeatureUpdate,
updateFeature, updateFeature,
saveCategory, saveCategory,
useWorktrees,
currentProject, currentProject,
onWorktreeCreated, onWorktreeCreated,
onWorktreeAutoSelect, onWorktreeAutoSelect,
currentWorktreeBranch,
] ]
); );
@@ -230,15 +248,29 @@ export function useBoardActions({
priority: number; priority: number;
planningMode?: PlanningMode; planningMode?: PlanningMode;
requirePlanApproval?: boolean; requirePlanApproval?: boolean;
workMode?: 'current' | 'auto' | 'custom';
}, },
descriptionHistorySource?: 'enhance' | 'edit', descriptionHistorySource?: 'enhance' | 'edit',
enhancementMode?: 'improve' | 'technical' | 'simplify' | 'acceptance' enhancementMode?: 'improve' | 'technical' | 'simplify' | 'acceptance'
) => { ) => {
const finalBranchName = updates.branchName || undefined; const workMode = updates.workMode || 'current';
// If worktrees enabled and a branch is specified, create the worktree now // Determine final branch name based on work mode
// This ensures the worktree exists before the feature starts let finalBranchName: string | undefined;
if (useWorktrees && finalBranchName && currentProject) {
if (workMode === 'current') {
finalBranchName = undefined;
} else if (workMode === 'auto') {
const baseBranch = currentWorktreeBranch || 'main';
const timestamp = Date.now();
const randomSuffix = Math.random().toString(36).substring(2, 6);
finalBranchName = `feature/${baseBranch}-${timestamp}-${randomSuffix}`;
} else {
finalBranchName = updates.branchName || undefined;
}
// Create worktree for 'auto' or 'custom' modes when we have a branch name
if ((workMode === 'auto' || workMode === 'custom') && finalBranchName && currentProject) {
try { try {
const api = getElectronAPI(); const api = getElectronAPI();
if (api?.worktree?.create) { if (api?.worktree?.create) {
@@ -287,9 +319,9 @@ export function useBoardActions({
persistFeatureUpdate, persistFeatureUpdate,
saveCategory, saveCategory,
setEditingFeature, setEditingFeature,
useWorktrees,
currentProject, currentProject,
onWorktreeCreated, onWorktreeCreated,
currentWorktreeBranch,
] ]
); );

View File

@@ -12,3 +12,4 @@ export * from './branch-selector';
export * from './planning-mode-selector'; export * from './planning-mode-selector';
export * from './planning-mode-select'; export * from './planning-mode-select';
export * from './ancestor-context-section'; export * from './ancestor-context-section';
export * from './work-mode-selector';

View File

@@ -0,0 +1,163 @@
'use client';
import { Label } from '@/components/ui/label';
import { BranchAutocomplete } from '@/components/ui/branch-autocomplete';
import { GitBranch, GitFork, Pencil } from 'lucide-react';
import { cn } from '@/lib/utils';
export type WorkMode = 'current' | 'auto' | 'custom';
interface WorkModeSelectorProps {
workMode: WorkMode;
onWorkModeChange: (mode: WorkMode) => void;
branchName: string;
onBranchNameChange: (branchName: string) => void;
branchSuggestions: string[];
branchCardCounts?: Record<string, number>;
currentBranch?: string;
disabled?: boolean;
testIdPrefix?: string;
}
const WORK_MODES = [
{
value: 'current' as const,
label: 'Current Branch',
description: 'Work directly on the selected branch',
icon: GitBranch,
},
{
value: 'auto' as const,
label: 'Auto Worktree',
description: 'Create isolated worktree automatically',
icon: GitFork,
},
{
value: 'custom' as const,
label: 'Custom Branch',
description: 'Specify a branch name',
icon: Pencil,
},
];
export function WorkModeSelector({
workMode,
onWorkModeChange,
branchName,
onBranchNameChange,
branchSuggestions,
branchCardCounts,
currentBranch,
disabled = false,
testIdPrefix = 'work-mode',
}: WorkModeSelectorProps) {
const hasError = workMode === 'custom' && !branchName.trim();
return (
<div className="space-y-3">
<Label id={`${testIdPrefix}-label`}>Work Mode</Label>
<div className="grid grid-cols-3 gap-2">
{WORK_MODES.map((mode) => {
const isSelected = workMode === mode.value;
const Icon = mode.icon;
return (
<button
key={mode.value}
type="button"
onClick={() => !disabled && onWorkModeChange(mode.value)}
disabled={disabled}
data-testid={`${testIdPrefix}-${mode.value}`}
className={cn(
'flex flex-col items-center gap-1.5 p-3 rounded-lg cursor-pointer transition-all duration-200',
'border-2 hover:border-primary/50',
isSelected
? 'border-primary bg-primary/10'
: 'border-border/50 bg-card/50 hover:bg-accent/30',
disabled && 'opacity-50 cursor-not-allowed'
)}
>
<div
className={cn(
'w-8 h-8 rounded-full flex items-center justify-center transition-colors',
isSelected ? 'bg-primary/20' : 'bg-muted'
)}
>
<Icon
className={cn(
'h-4 w-4 transition-colors',
isSelected ? 'text-primary' : 'text-muted-foreground'
)}
/>
</div>
<span
className={cn(
'font-medium text-xs text-center',
isSelected ? 'text-foreground' : 'text-muted-foreground'
)}
>
{mode.label}
</span>
</button>
);
})}
</div>
{/* Description text based on selected mode */}
<p className="text-xs text-muted-foreground">
{workMode === 'current' && (
<>
Work will be done directly on{' '}
{currentBranch ? (
<span className="font-medium">{currentBranch}</span>
) : (
'the current branch'
)}
. No isolation.
</>
)}
{workMode === 'auto' && (
<>
A new worktree will be created automatically based on{' '}
{currentBranch ? (
<span className="font-medium">{currentBranch}</span>
) : (
'the current branch'
)}{' '}
when this card is created.
</>
)}
{workMode === 'custom' && (
<>Specify a branch name below. A worktree will be created if it doesn't exist.</>
)}
</p>
{/* Branch input for custom mode */}
{workMode === 'custom' && (
<div className="space-y-1">
<BranchAutocomplete
value={branchName}
onChange={onBranchNameChange}
branches={branchSuggestions}
branchCardCounts={branchCardCounts}
placeholder="Select or create branch..."
data-testid={`${testIdPrefix}-branch-input`}
disabled={disabled}
error={hasError}
/>
{hasError && (
<p className="text-xs text-destructive">
Branch name is required for custom branch mode.
</p>
)}
</div>
)}
{disabled && (
<p className="text-xs text-muted-foreground italic">
Work mode cannot be changed after work has started.
</p>
)}
</div>
);
}

View File

@@ -358,9 +358,6 @@ export function FeatureDefaultsSection({
> >
<GitBranch className="w-4 h-4 text-brand-500" /> <GitBranch className="w-4 h-4 text-brand-500" />
Enable Git Worktree Isolation Enable Git Worktree Isolation
<span className="text-[10px] px-1.5 py-0.5 rounded-md bg-amber-500/15 text-amber-500 border border-amber-500/20 font-medium">
experimental
</span>
</Label> </Label>
<p className="text-xs text-muted-foreground/80 leading-relaxed"> <p className="text-xs text-muted-foreground/80 leading-relaxed">
Creates isolated git branches for each feature. When disabled, agents work directly in Creates isolated git branches for each feature. When disabled, agents work directly in

View File

@@ -560,7 +560,7 @@ export function hydrateStoreFromSettings(settings: GlobalSettings): void {
defaultSkipTests: settings.defaultSkipTests ?? true, defaultSkipTests: settings.defaultSkipTests ?? true,
enableDependencyBlocking: settings.enableDependencyBlocking ?? true, enableDependencyBlocking: settings.enableDependencyBlocking ?? true,
skipVerificationInAutoMode: settings.skipVerificationInAutoMode ?? false, skipVerificationInAutoMode: settings.skipVerificationInAutoMode ?? false,
useWorktrees: settings.useWorktrees ?? false, useWorktrees: settings.useWorktrees ?? true,
showProfilesOnly: settings.showProfilesOnly ?? false, showProfilesOnly: settings.showProfilesOnly ?? false,
defaultPlanningMode: settings.defaultPlanningMode ?? 'skip', defaultPlanningMode: settings.defaultPlanningMode ?? 'skip',
defaultRequirePlanApproval: settings.defaultRequirePlanApproval ?? false, defaultRequirePlanApproval: settings.defaultRequirePlanApproval ?? false,

View File

@@ -523,7 +523,7 @@ export interface AppState {
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)
// Worktree Settings // Worktree Settings
useWorktrees: boolean; // Whether to use git worktree isolation for features (default: false) useWorktrees: boolean; // Whether to use git worktree isolation for features (default: true)
// User-managed Worktrees (per-project) // User-managed Worktrees (per-project)
// projectPath -> { path: worktreePath or null for main, branch: branch name } // projectPath -> { path: worktreePath or null for main, branch: branch name }
@@ -1172,7 +1172,7 @@ 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)
useWorktrees: false, // Default to disabled (worktree feature is experimental) useWorktrees: true, // Default to enabled (git worktree isolation)
currentWorktreeByProject: {}, currentWorktreeByProject: {},
worktreesByProject: {}, worktreesByProject: {},
showProfilesOnly: false, // Default to showing all options (not profiles only) showProfilesOnly: false, // Default to showing all options (not profiles only)

View File

@@ -785,7 +785,7 @@ export const DEFAULT_GLOBAL_SETTINGS: GlobalSettings = {
defaultSkipTests: true, defaultSkipTests: true,
enableDependencyBlocking: true, enableDependencyBlocking: true,
skipVerificationInAutoMode: false, skipVerificationInAutoMode: false,
useWorktrees: false, useWorktrees: true,
showProfilesOnly: false, showProfilesOnly: false,
defaultPlanningMode: 'skip', defaultPlanningMode: 'skip',
defaultRequirePlanApproval: false, defaultRequirePlanApproval: false,