fix(core): handle policy ALLOW for exit_plan_mode (#21802)

This commit is contained in:
Michael Ramos
2026-03-12 07:43:40 -07:00
committed by GitHub
parent 34709dc62d
commit 7506b00488
2 changed files with 30 additions and 2 deletions

View File

@@ -339,6 +339,26 @@ Ask the user for specific feedback on how to improve the plan.`,
});
});
describe('execute when shouldConfirmExecute is never called', () => {
it('should approve with DEFAULT mode when approvalPayload is null (policy ALLOW skips confirmation)', async () => {
const planRelativePath = createPlanFile('test.md', '# Content');
const invocation = tool.build({ plan_path: planRelativePath });
// Simulate the scheduler's policy ALLOW path: execute() is called
// directly without ever calling shouldConfirmExecute(), leaving
// approvalPayload null.
const result = await invocation.execute(new AbortController().signal);
const expectedPath = path.join(mockPlansDir, 'test.md');
expect(result.llmContent).toContain('Plan approved');
expect(result.returnDisplay).toContain('Plan approved');
expect(mockConfig.setApprovalMode).toHaveBeenCalledWith(
ApprovalMode.DEFAULT,
);
expect(mockConfig.setApprovedPlanPath).toHaveBeenCalledWith(expectedPath);
});
});
describe('getApprovalModeDescription (internal)', () => {
it('should handle all valid approval modes', async () => {
const planRelativePath = createPlanFile('test.md', '# Content');

View File

@@ -203,8 +203,16 @@ export class ExitPlanModeInvocation extends BaseToolInvocation<
};
}
const payload = this.approvalPayload;
if (payload?.approved) {
// When a user policy grants `allow` for exit_plan_mode, the scheduler
// skips the confirmation phase entirely and shouldConfirmExecute is never
// called, leaving approvalPayload null. Treat that as an approval with
// the default mode — consistent with the ALLOW branch inside
// shouldConfirmExecute.
const payload = this.approvalPayload ?? {
approved: true,
approvalMode: ApprovalMode.DEFAULT,
};
if (payload.approved) {
const newMode = payload.approvalMode ?? ApprovalMode.DEFAULT;
if (newMode === ApprovalMode.PLAN || newMode === ApprovalMode.YOLO) {