リトライ時でタスクにつめるようにする
This commit is contained in:
parent
8ffe0592ef
commit
9fc8ab73fd
@ -2,7 +2,7 @@
|
|||||||
* Tests for /retry slash command in the conversation loop.
|
* Tests for /retry slash command in the conversation loop.
|
||||||
*
|
*
|
||||||
* Verifies:
|
* Verifies:
|
||||||
* - /retry with previousOrderContent returns execute action with order content
|
* - /retry with previousOrderContent uses post-summary action selection
|
||||||
* - /retry without previousOrderContent shows error and continues loop
|
* - /retry without previousOrderContent shows error and continues loop
|
||||||
* - /retry in retry mode with order.md context in system prompt
|
* - /retry in retry mode with order.md context in system prompt
|
||||||
*/
|
*/
|
||||||
@ -18,6 +18,7 @@ import {
|
|||||||
createMockProvider,
|
createMockProvider,
|
||||||
type MockProviderCapture,
|
type MockProviderCapture,
|
||||||
} from './helpers/stdinSimulator.js';
|
} from './helpers/stdinSimulator.js';
|
||||||
|
import { selectOption } from '../shared/prompt/index.js';
|
||||||
|
|
||||||
// --- Mocks (infrastructure only) ---
|
// --- Mocks (infrastructure only) ---
|
||||||
|
|
||||||
@ -147,7 +148,8 @@ describe('/retry slash command', () => {
|
|||||||
rmSync(tmpDir, { recursive: true, force: true });
|
rmSync(tmpDir, { recursive: true, force: true });
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should execute with previous order content when /retry is used', async () => {
|
it('should route previous order content through action selection when /retry is used', async () => {
|
||||||
|
vi.mocked(selectOption).mockResolvedValueOnce('save_task');
|
||||||
const orderContent = '# Task Order\n\nImplement feature X with tests.';
|
const orderContent = '# Task Order\n\nImplement feature X with tests.';
|
||||||
setupRawStdin(toRawInputs(['/retry']));
|
setupRawStdin(toRawInputs(['/retry']));
|
||||||
setupProvider([]);
|
setupProvider([]);
|
||||||
@ -155,7 +157,7 @@ describe('/retry slash command', () => {
|
|||||||
const retryContext = buildRetryContext({ previousOrderContent: orderContent });
|
const retryContext = buildRetryContext({ previousOrderContent: orderContent });
|
||||||
const result = await runRetryMode(tmpDir, retryContext, orderContent);
|
const result = await runRetryMode(tmpDir, retryContext, orderContent);
|
||||||
|
|
||||||
expect(result.action).toBe('execute');
|
expect(result.action).toBe('save_task');
|
||||||
expect(result.task).toBe(orderContent);
|
expect(result.task).toBe(orderContent);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -170,6 +172,18 @@ describe('/retry slash command', () => {
|
|||||||
expect(result.action).toBe('cancel');
|
expect(result.action).toBe('cancel');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should continue when /retry is selected with continue action', async () => {
|
||||||
|
vi.mocked(selectOption).mockResolvedValueOnce('continue');
|
||||||
|
setupRawStdin(toRawInputs(['/retry', '/cancel']));
|
||||||
|
setupProvider([]);
|
||||||
|
|
||||||
|
const orderContent = '# Task Order\n\nImplement feature X with tests.';
|
||||||
|
const retryContext = buildRetryContext({ previousOrderContent: orderContent });
|
||||||
|
const result = await runRetryMode(tmpDir, retryContext, orderContent);
|
||||||
|
|
||||||
|
expect(result.action).toBe('cancel');
|
||||||
|
});
|
||||||
|
|
||||||
it('should inject order.md content into retry system prompt', async () => {
|
it('should inject order.md content into retry system prompt', async () => {
|
||||||
const orderContent = '# Build login page\n\nWith OAuth2 support.';
|
const orderContent = '# Build login page\n\nWith OAuth2 support.';
|
||||||
setupRawStdin(toRawInputs(['check the order', '/cancel']));
|
setupRawStdin(toRawInputs(['check the order', '/cancel']));
|
||||||
|
|||||||
@ -144,6 +144,18 @@ export async function runConversationLoop(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function handleSummaryAction(task: string): Promise<InteractiveModeResult | null> {
|
||||||
|
const selectedAction = strategy.selectAction
|
||||||
|
? await strategy.selectAction(task, ctx.lang)
|
||||||
|
: await selectPostSummaryAction(task, ui.proposed, ui);
|
||||||
|
if (selectedAction === 'continue' || selectedAction === null) {
|
||||||
|
info(ui.continuePrompt);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
log.info('Conversation action selected', { action: selectedAction, messageCount: history.length });
|
||||||
|
return { action: selectedAction, task };
|
||||||
|
}
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
const input = await readMultilineInput(chalk.green('> '));
|
const input = await readMultilineInput(chalk.green('> '));
|
||||||
|
|
||||||
@ -203,8 +215,12 @@ export async function runConversationLoop(
|
|||||||
info(ui.retryNoOrder);
|
info(ui.retryNoOrder);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
log.info('Retry command — resubmitting previous order.md');
|
log.info('Retry command — using previous order.md');
|
||||||
return { action: 'execute', task: strategy.previousOrderContent };
|
const selectedAction = await handleSummaryAction(strategy.previousOrderContent);
|
||||||
|
if (selectedAction === null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return selectedAction;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SlashCommand.Go: {
|
case SlashCommand.Go: {
|
||||||
@ -234,15 +250,11 @@ export async function runConversationLoop(
|
|||||||
return { action: 'cancel', task: '' };
|
return { action: 'cancel', task: '' };
|
||||||
}
|
}
|
||||||
const task = summaryResult.content.trim();
|
const task = summaryResult.content.trim();
|
||||||
const selectedAction = strategy.selectAction
|
const selectedAction = await handleSummaryAction(task);
|
||||||
? await strategy.selectAction(task, ctx.lang)
|
if (selectedAction === null) {
|
||||||
: await selectPostSummaryAction(task, ui.proposed, ui);
|
|
||||||
if (selectedAction === 'continue' || selectedAction === null) {
|
|
||||||
info(ui.continuePrompt);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
log.info('Conversation action selected', { action: selectedAction, messageCount: history.length });
|
return selectedAction;
|
||||||
return { action: selectedAction, task };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case SlashCommand.Replay: {
|
case SlashCommand.Replay: {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user