Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions docs/cli/plan-mode.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,9 @@ structure, and consultation level are proportional to the task's complexity:
- **Iterate:** Provide feedback to refine the plan.
- **Refine manually:** Press **Ctrl + X** to open the plan file in your
[preferred external editor]. This allows you to manually refine the plan
steps before approval. The CLI will automatically refresh and show the
updated plan after you save and close the editor.
steps before approval. If you make any changes and save the file, the CLI
will automatically send the updated plan back to the agent for review and
iteration.

For more complex or specialized planning tasks, you can
[customize the planning workflow with skills](#customizing-planning-with-skills).
Expand Down
22 changes: 3 additions & 19 deletions packages/cli/src/ui/components/ExitPlanModeDialog.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import { waitFor } from '../../test-utils/async.js';
import { ExitPlanModeDialog } from './ExitPlanModeDialog.js';
import { useKeypress } from '../hooks/useKeypress.js';
import { keyMatchers, Command } from '../keyMatchers.js';
import { openFileInEditor } from '../utils/editorUtils.js';
import {
ApprovalMode,
validatePlanContent,
Expand Down Expand Up @@ -41,10 +40,6 @@ vi.mock('node:fs', async (importOriginal) => {
...actual,
existsSync: vi.fn(),
realpathSync: vi.fn((p) => p),
promises: {
...actual.promises,
readFile: vi.fn(),
},
};
});

Expand Down Expand Up @@ -546,7 +541,7 @@ Implement a comprehensive authentication system with multiple providers.
expect(onFeedback).not.toHaveBeenCalled();
});

it('opens plan in external editor when Ctrl+X is pressed', async () => {
it('automatically submits feedback when Ctrl+X is used to edit the plan', async () => {
const { stdin, lastFrame } = renderDialog({ useAlternateBuffer });

await act(async () => {
Expand All @@ -557,27 +552,16 @@ Implement a comprehensive authentication system with multiple providers.
expect(lastFrame()).toContain('Add user authentication');
});

// Reset the mock to track the second call during refresh
vi.mocked(processSingleFileContent).mockClear();

// Press Ctrl+X
await act(async () => {
writeKey(stdin, '\x18'); // Ctrl+X
});

await waitFor(() => {
expect(openFileInEditor).toHaveBeenCalledWith(
mockPlanFullPath,
expect.anything(),
expect.anything(),
undefined,
expect(onFeedback).toHaveBeenCalledWith(
'I have edited the plan or annotated it with feedback. Review the edited plan, update if necessary, and present it again for approval.',
);
});

// Verify that content is refreshed (processSingleFileContent called again)
await waitFor(() => {
expect(processSingleFileContent).toHaveBeenCalled();
});
});
},
);
Expand Down
6 changes: 5 additions & 1 deletion packages/cli/src/ui/components/ExitPlanModeDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -156,11 +156,15 @@ export const ExitPlanModeDialog: React.FC<ExitPlanModeDialogProps> = ({
const handleOpenEditor = useCallback(async () => {
try {
await openFileInEditor(planPath, stdin, setRawMode, getPreferredEditor());

onFeedback(
'I have edited the plan or annotated it with feedback. Review the edited plan, update if necessary, and present it again for approval.',
);
refresh();
} catch (err) {
debugLogger.error('Failed to open plan in editor:', err);
}
}, [planPath, stdin, setRawMode, getPreferredEditor, refresh]);
}, [planPath, stdin, setRawMode, getPreferredEditor, refresh, onFeedback]);

useKeypress(
(key) => {
Expand Down
Loading