diff --git a/src/__tests__/renderer/hooks/useWizardHandlers.test.ts b/src/__tests__/renderer/hooks/useWizardHandlers.test.ts
index 2c2d8efad..4493ec1e3 100644
--- a/src/__tests__/renderer/hooks/useWizardHandlers.test.ts
+++ b/src/__tests__/renderer/hooks/useWizardHandlers.test.ts
@@ -1888,6 +1888,76 @@ describe('useWizardHandlers', () => {
);
});
+ it('auto-starts batch run with all documents when runAllDocuments is true', async () => {
+ useSessionStore.setState({ sessions: [], activeSessionId: null });
+
+ const deps = createMockDeps({
+ wizardContext: {
+ state: {
+ currentStep: 'review' as any,
+ isOpen: true,
+ selectedAgent: 'claude-code',
+ availableAgents: [],
+ agentName: 'Test',
+ directoryPath: '/projects/test',
+ isGitRepo: false,
+ detectedAgentPath: null,
+ directoryError: null,
+ hasExistingAutoRunDocs: false,
+ existingDocsCount: 0,
+ existingDocsChoice: null,
+ conversationHistory: [],
+ confidenceLevel: 90,
+ isReadyToProceed: true,
+ isConversationLoading: false,
+ conversationError: null,
+ generatedDocuments: [
+ { filename: 'phase-1.md', content: '# Phase 1', taskCount: 3 },
+ { filename: 'phase-2.md', content: '# Phase 2', taskCount: 5 },
+ { filename: 'phase-3.md', content: '# Phase 3', taskCount: 2 },
+ ],
+ currentDocumentIndex: 0,
+ isGeneratingDocuments: false,
+ generationError: null,
+ editedPhase1Content: null,
+ runAllDocuments: true,
+ wantsTour: false,
+ isComplete: false,
+ createdSessionId: null,
+ } as any,
+ completeWizard: vi.fn(),
+ clearResumeState: vi.fn(),
+ },
+ });
+
+ const { result } = renderHook(() => useWizardHandlers(deps));
+
+ await act(async () => {
+ await result.current.handleWizardLaunchSession(false);
+ });
+
+ // Wait for the setTimeout batch run
+ await act(async () => {
+ await new Promise((r) => setTimeout(r, 600));
+ });
+
+ expect(deps.startBatchRun).toHaveBeenCalledWith(
+ expect.any(String),
+ expect.objectContaining({
+ documents: expect.arrayContaining([
+ expect.objectContaining({ filename: 'phase-1' }),
+ expect.objectContaining({ filename: 'phase-2' }),
+ expect.objectContaining({ filename: 'phase-3' }),
+ ]),
+ }),
+ expect.stringContaining('Auto Run Docs')
+ );
+
+ // Should have exactly 3 documents in the batch
+ const batchConfig = deps.startBatchRun.mock.calls[0][1];
+ expect(batchConfig.documents).toHaveLength(3);
+ });
+
it('starts tour when wantsTour is true', async () => {
useSessionStore.setState({ sessions: [], activeSessionId: null });
diff --git a/src/renderer/components/SettingCheckbox.tsx b/src/renderer/components/SettingCheckbox.tsx
index 1fec960e6..65edc0c97 100644
--- a/src/renderer/components/SettingCheckbox.tsx
+++ b/src/renderer/components/SettingCheckbox.tsx
@@ -1,6 +1,7 @@
import React from 'react';
import type { Theme } from '../types';
import type { LucideIcon } from 'lucide-react';
+import { ToggleSwitch } from './ui/ToggleSwitch';
export interface SettingCheckboxProps {
/** The icon to display next to the section label */
@@ -62,24 +63,7 @@ export function SettingCheckbox({
)}
-
+
);
diff --git a/src/renderer/components/Wizard/MaestroWizard.tsx b/src/renderer/components/Wizard/MaestroWizard.tsx
index 155d4e54d..0a7718295 100644
--- a/src/renderer/components/Wizard/MaestroWizard.tsx
+++ b/src/renderer/components/Wizard/MaestroWizard.tsx
@@ -456,7 +456,7 @@ export function MaestroWizard({
};
@@ -375,6 +383,9 @@ function wizardReducer(state: WizardState, action: WizardAction): WizardState {
case 'SET_EDITED_PHASE1_CONTENT':
return { ...state, editedPhase1Content: action.content };
+ case 'SET_RUN_ALL_DOCUMENTS':
+ return { ...state, runAllDocuments: action.runAll };
+
case 'SET_WANTS_TOUR':
return { ...state, wantsTour: action.wantsTour };
@@ -408,6 +419,7 @@ export interface SerializableWizardState {
isReadyToProceed: boolean;
generatedDocuments: GeneratedDocument[];
editedPhase1Content: string | null;
+ runAllDocuments: boolean;
wantsTour: boolean;
/** Per-session SSH remote configuration (for remote execution) */
sessionSshRemoteConfig?: {
@@ -504,6 +516,10 @@ export interface WizardContextAPI {
/** Get current Phase 1 content (edited or original) */
getPhase1Content: () => string;
+ // Launch Options
+ /** Set whether to run all documents or just the first */
+ setRunAllDocuments: (runAll: boolean) => void;
+
// Tour
/** Set whether user wants the tour */
setWantsTour: (wantsTour: boolean) => void;
@@ -735,6 +751,11 @@ export function WizardProvider({ children }: WizardProviderProps) {
return phase1Doc?.content || '';
}, [state.editedPhase1Content, state.generatedDocuments]);
+ // Launch Options
+ const setRunAllDocuments = useCallback((runAll: boolean) => {
+ dispatch({ type: 'SET_RUN_ALL_DOCUMENTS', runAll });
+ }, []);
+
// Tour
const setWantsTour = useCallback((wantsTour: boolean) => {
dispatch({ type: 'SET_WANTS_TOUR', wantsTour });
@@ -760,6 +781,7 @@ export function WizardProvider({ children }: WizardProviderProps) {
isReadyToProceed: state.isReadyToProceed,
generatedDocuments: state.generatedDocuments,
editedPhase1Content: state.editedPhase1Content,
+ runAllDocuments: state.runAllDocuments,
wantsTour: state.wantsTour,
sessionSshRemoteConfig: state.sessionSshRemoteConfig,
};
@@ -774,6 +796,7 @@ export function WizardProvider({ children }: WizardProviderProps) {
state.isReadyToProceed,
state.generatedDocuments,
state.editedPhase1Content,
+ state.runAllDocuments,
state.wantsTour,
state.sessionSshRemoteConfig,
]);
@@ -842,6 +865,7 @@ export function WizardProvider({ children }: WizardProviderProps) {
isReadyToProceed: currentState.isReadyToProceed,
generatedDocuments: currentState.generatedDocuments,
editedPhase1Content: currentState.editedPhase1Content,
+ runAllDocuments: currentState.runAllDocuments,
wantsTour: currentState.wantsTour,
};
window.maestro.settings.set('wizardResumeState', serializableState);
@@ -898,6 +922,9 @@ export function WizardProvider({ children }: WizardProviderProps) {
setEditedPhase1Content,
getPhase1Content,
+ // Launch Options
+ setRunAllDocuments,
+
// Tour
setWantsTour,
@@ -947,6 +974,7 @@ export function WizardProvider({ children }: WizardProviderProps) {
setGenerationError,
setEditedPhase1Content,
getPhase1Content,
+ setRunAllDocuments,
setWantsTour,
completeWizard,
saveStateForResume,
diff --git a/src/renderer/components/Wizard/screens/PhaseReviewScreen.tsx b/src/renderer/components/Wizard/screens/PhaseReviewScreen.tsx
index 77a2797d9..00303e919 100644
--- a/src/renderer/components/Wizard/screens/PhaseReviewScreen.tsx
+++ b/src/renderer/components/Wizard/screens/PhaseReviewScreen.tsx
@@ -21,6 +21,7 @@ import { useWizard } from '../WizardContext';
import { AUTO_RUN_FOLDER_NAME } from '../services/phaseGenerator';
import { ScreenReaderAnnouncement } from '../ScreenReaderAnnouncement';
import { DocumentEditor } from '../shared/DocumentEditor';
+import { ToggleSwitch } from '../../ui/ToggleSwitch';
import { formatShortcutKeys } from '../../../utils/shortcutFormatter';
// Auto-save debounce delay in milliseconds
@@ -67,8 +68,14 @@ function DocumentReview({
) => void;
wizardStartTime?: number;
}): JSX.Element {
- const { state, setEditedPhase1Content, getPhase1Content, setWantsTour, setCurrentDocumentIndex } =
- useWizard();
+ const {
+ state,
+ setEditedPhase1Content,
+ getPhase1Content,
+ setWantsTour,
+ setCurrentDocumentIndex,
+ setRunAllDocuments,
+ } = useWizard();
const { generatedDocuments, directoryPath, currentDocumentIndex } = state;
const currentDoc = generatedDocuments[currentDocumentIndex] || generatedDocuments[0];
@@ -479,6 +486,38 @@ function DocumentReview({
backgroundColor: theme.colors.bgSidebar,
}}
>
+ {/* Run All toggle - only shown when there are multiple documents */}
+ {generatedDocuments.length > 1 && (
+
setRunAllDocuments(!state.runAllDocuments)}
+ role="button"
+ tabIndex={0}
+ onKeyDown={(e) => {
+ if (e.key === 'Enter' || e.key === ' ') {
+ e.preventDefault();
+ setRunAllDocuments(!state.runAllDocuments);
+ }
+ }}
+ >
+
+
+ {state.runAllDocuments ? 'Auto Run All Phases' : 'Auto Run First Phase Only For Now'}
+
+
+ )}
+
{/* Primary button - Ready to Go */}