feat(plan): support annotating plans with feedback for iteration (#20876)

This commit is contained in:
Adib234
2026-03-02 18:03:59 -05:00
committed by GitHub
parent 06ddfa5c4c
commit 01927a36d1
3 changed files with 11 additions and 22 deletions
+3 -2
View File
@@ -109,8 +109,9 @@ structure, and consultation level are proportional to the task's complexity:
- **Iterate:** Provide feedback to refine the plan. - **Iterate:** Provide feedback to refine the plan.
- **Refine manually:** Press **Ctrl + X** to open the plan file in your - **Refine manually:** Press **Ctrl + X** to open the plan file in your
[preferred external editor]. This allows you to manually refine the plan [preferred external editor]. This allows you to manually refine the plan
steps before approval. The CLI will automatically refresh and show the steps before approval. If you make any changes and save the file, the CLI
updated plan after you save and close the editor. will automatically send the updated plan back to the agent for review and
iteration.
For more complex or specialized planning tasks, you can For more complex or specialized planning tasks, you can
[customize the planning workflow with skills](#customizing-planning-with-skills). [customize the planning workflow with skills](#customizing-planning-with-skills).
@@ -11,7 +11,6 @@ import { waitFor } from '../../test-utils/async.js';
import { ExitPlanModeDialog } from './ExitPlanModeDialog.js'; import { ExitPlanModeDialog } from './ExitPlanModeDialog.js';
import { useKeypress } from '../hooks/useKeypress.js'; import { useKeypress } from '../hooks/useKeypress.js';
import { keyMatchers, Command } from '../keyMatchers.js'; import { keyMatchers, Command } from '../keyMatchers.js';
import { openFileInEditor } from '../utils/editorUtils.js';
import { import {
ApprovalMode, ApprovalMode,
validatePlanContent, validatePlanContent,
@@ -41,10 +40,6 @@ vi.mock('node:fs', async (importOriginal) => {
...actual, ...actual,
existsSync: vi.fn(), existsSync: vi.fn(),
realpathSync: vi.fn((p) => p), realpathSync: vi.fn((p) => p),
promises: {
...actual.promises,
readFile: vi.fn(),
},
}; };
}); });
@@ -546,7 +541,7 @@ Implement a comprehensive authentication system with multiple providers.
expect(onFeedback).not.toHaveBeenCalled(); 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 }); const { stdin, lastFrame } = renderDialog({ useAlternateBuffer });
await act(async () => { await act(async () => {
@@ -557,27 +552,16 @@ Implement a comprehensive authentication system with multiple providers.
expect(lastFrame()).toContain('Add user authentication'); expect(lastFrame()).toContain('Add user authentication');
}); });
// Reset the mock to track the second call during refresh
vi.mocked(processSingleFileContent).mockClear();
// Press Ctrl+X // Press Ctrl+X
await act(async () => { await act(async () => {
writeKey(stdin, '\x18'); // Ctrl+X writeKey(stdin, '\x18'); // Ctrl+X
}); });
await waitFor(() => { await waitFor(() => {
expect(openFileInEditor).toHaveBeenCalledWith( expect(onFeedback).toHaveBeenCalledWith(
mockPlanFullPath, 'I have edited the plan or annotated it with feedback. Review the edited plan, update if necessary, and present it again for approval.',
expect.anything(),
expect.anything(),
undefined,
); );
}); });
// Verify that content is refreshed (processSingleFileContent called again)
await waitFor(() => {
expect(processSingleFileContent).toHaveBeenCalled();
});
}); });
}, },
); );
@@ -156,11 +156,15 @@ export const ExitPlanModeDialog: React.FC<ExitPlanModeDialogProps> = ({
const handleOpenEditor = useCallback(async () => { const handleOpenEditor = useCallback(async () => {
try { try {
await openFileInEditor(planPath, stdin, setRawMode, getPreferredEditor()); 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(); refresh();
} catch (err) { } catch (err) {
debugLogger.error('Failed to open plan in editor:', err); debugLogger.error('Failed to open plan in editor:', err);
} }
}, [planPath, stdin, setRawMode, getPreferredEditor, refresh]); }, [planPath, stdin, setRawMode, getPreferredEditor, refresh, onFeedback]);
useKeypress( useKeypress(
(key) => { (key) => {