takt: github-issue-328-tasuku-ritora (#340)
This commit is contained in:
parent
9e68f086d4
commit
b309233aeb
@ -70,7 +70,11 @@ vi.mock('../features/interactive/index.js', () => ({
|
||||
loadRunSessionContext: vi.fn(),
|
||||
getRunPaths: vi.fn(() => ({ logsDir: '/tmp/logs', reportsDir: '/tmp/reports' })),
|
||||
formatRunSessionForPrompt: vi.fn(() => ({
|
||||
runTask: '', runPiece: '', runStatus: '', runMovementLogs: '', runReports: '',
|
||||
runTask: '',
|
||||
runPiece: 'default',
|
||||
runStatus: '',
|
||||
runMovementLogs: '',
|
||||
runReports: '',
|
||||
})),
|
||||
runRetryMode: (...args: unknown[]) => mockRunRetryMode(...args),
|
||||
findPreviousOrderContent: vi.fn(() => null),
|
||||
@ -91,6 +95,17 @@ vi.mock('../features/tasks/execute/taskExecution.js', () => ({
|
||||
executeAndCompleteTask: (...args: unknown[]) => mockExecuteAndCompleteTask(...args),
|
||||
}));
|
||||
|
||||
vi.mock('../shared/i18n/index.js', () => ({
|
||||
getLabel: vi.fn((key: string) => {
|
||||
const labels: Record<string, string> = {
|
||||
'retry.workflowPrompt': 'Select workflow:',
|
||||
'retry.usePreviousWorkflow': 'Use previous',
|
||||
'retry.changeWorkflow': 'Change workflow',
|
||||
};
|
||||
return labels[key] ?? key;
|
||||
}),
|
||||
}));
|
||||
|
||||
import { retryFailedTask } from '../features/tasks/list/taskRetryActions.js';
|
||||
import type { TaskListItem } from '../infra/task/types.js';
|
||||
import type { PieceConfig } from '../core/models/index.js';
|
||||
@ -262,4 +277,54 @@ describe('retryFailedTask', () => {
|
||||
|
||||
expect(mockRequeueTask).toHaveBeenCalledWith('my-task', ['failed'], undefined, '既存ノート\n\n追加指示A');
|
||||
});
|
||||
|
||||
describe('when previous workflow exists', () => {
|
||||
beforeEach(() => {
|
||||
mockFindRunForTask.mockReturnValue('run-123');
|
||||
});
|
||||
|
||||
it('should show workflow selection prompt when runInfo.piece exists', async () => {
|
||||
const task = makeFailedTask();
|
||||
|
||||
await retryFailedTask(task, '/project');
|
||||
|
||||
expect(mockSelectOptionWithDefault).toHaveBeenCalledWith(
|
||||
'Select workflow:',
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({ value: 'use_previous' }),
|
||||
expect.objectContaining({ value: 'change' }),
|
||||
]),
|
||||
'use_previous',
|
||||
);
|
||||
});
|
||||
|
||||
it('should use previous workflow when use_previous is selected', async () => {
|
||||
const task = makeFailedTask();
|
||||
mockSelectOptionWithDefault.mockResolvedValue('use_previous');
|
||||
|
||||
await retryFailedTask(task, '/project');
|
||||
|
||||
expect(mockSelectPiece).not.toHaveBeenCalled();
|
||||
expect(mockLoadPieceByIdentifier).toHaveBeenCalledWith('default', '/project');
|
||||
});
|
||||
|
||||
it('should call selectPiece when change is selected', async () => {
|
||||
const task = makeFailedTask();
|
||||
mockSelectOptionWithDefault.mockResolvedValue('change');
|
||||
|
||||
await retryFailedTask(task, '/project');
|
||||
|
||||
expect(mockSelectPiece).toHaveBeenCalledWith('/project');
|
||||
});
|
||||
|
||||
it('should return false when workflow selection is cancelled', async () => {
|
||||
const task = makeFailedTask();
|
||||
mockSelectOptionWithDefault.mockResolvedValue(null);
|
||||
|
||||
const result = await retryFailedTask(task, '/project');
|
||||
|
||||
expect(result).toBe(false);
|
||||
expect(mockLoadPieceByIdentifier).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -11,6 +11,7 @@ import { TaskRunner } from '../../../infra/task/index.js';
|
||||
import { loadPieceByIdentifier, resolvePieceConfigValue, getPieceDescription } from '../../../infra/config/index.js';
|
||||
import { selectPiece } from '../../pieceSelection/index.js';
|
||||
import { selectOptionWithDefault } from '../../../shared/prompt/index.js';
|
||||
import { getLabel } from '../../../shared/i18n/index.js';
|
||||
import { info, header, blankLine, status } from '../../../shared/ui/index.js';
|
||||
import { createLogger } from '../../../shared/utils/index.js';
|
||||
import type { PieceConfig } from '../../../core/models/index.js';
|
||||
@ -128,10 +129,44 @@ export async function retryFailedTask(
|
||||
|
||||
displayFailureInfo(task);
|
||||
|
||||
const selectedPiece = await selectPiece(projectDir);
|
||||
if (!selectedPiece) {
|
||||
info('Cancelled');
|
||||
return false;
|
||||
const matchedSlug = findRunForTask(worktreePath, task.content);
|
||||
const runInfo = matchedSlug ? buildRetryRunInfo(worktreePath, matchedSlug) : null;
|
||||
|
||||
let selectedPiece: string;
|
||||
if (runInfo?.piece) {
|
||||
const usePreviousLabel = getLabel('retry.usePreviousWorkflow');
|
||||
const changeWorkflowLabel = getLabel('retry.changeWorkflow');
|
||||
const choice = await selectOptionWithDefault(
|
||||
getLabel('retry.workflowPrompt'),
|
||||
[
|
||||
{ label: `${runInfo.piece} - ${usePreviousLabel}`, value: 'use_previous' },
|
||||
{ label: changeWorkflowLabel, value: 'change' },
|
||||
],
|
||||
'use_previous',
|
||||
);
|
||||
|
||||
if (choice === null) {
|
||||
info('Cancelled');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (choice === 'use_previous') {
|
||||
selectedPiece = runInfo.piece;
|
||||
} else {
|
||||
const selected = await selectPiece(projectDir);
|
||||
if (!selected) {
|
||||
info('Cancelled');
|
||||
return false;
|
||||
}
|
||||
selectedPiece = selected;
|
||||
}
|
||||
} else {
|
||||
const selected = await selectPiece(projectDir);
|
||||
if (!selected) {
|
||||
info('Cancelled');
|
||||
return false;
|
||||
}
|
||||
selectedPiece = selected;
|
||||
}
|
||||
|
||||
const previewCount = resolvePieceConfigValue(projectDir, 'interactivePreviewMovements');
|
||||
@ -155,8 +190,6 @@ export async function retryFailedTask(
|
||||
};
|
||||
|
||||
// Runs data lives in the worktree (written during previous execution)
|
||||
const matchedSlug = findRunForTask(worktreePath, task.content);
|
||||
const runInfo = matchedSlug ? buildRetryRunInfo(worktreePath, matchedSlug) : null;
|
||||
const previousOrderContent = findPreviousOrderContent(worktreePath, matchedSlug);
|
||||
|
||||
blankLine();
|
||||
|
||||
@ -96,6 +96,9 @@ instruct:
|
||||
retry:
|
||||
ui:
|
||||
intro: "Retry mode - describe additional instructions. Commands: /go (create instruction & run), /retry (rerun previous order), /cancel (exit)"
|
||||
workflowPrompt: "Select workflow:"
|
||||
usePreviousWorkflow: "Use previous"
|
||||
changeWorkflow: "Change workflow"
|
||||
|
||||
run:
|
||||
notifyComplete: "Run complete ({total} tasks)"
|
||||
|
||||
@ -96,6 +96,9 @@ instruct:
|
||||
retry:
|
||||
ui:
|
||||
intro: "リトライモード - 追加指示を入力してください。コマンド: /go(指示書作成・実行), /retry(前回の指示書で再実行), /cancel(終了)"
|
||||
workflowPrompt: "ワークフローを選択:"
|
||||
usePreviousWorkflow: "前回のまま使用"
|
||||
changeWorkflow: "ワークフローを変更"
|
||||
|
||||
run:
|
||||
notifyComplete: "run完了 ({total} tasks)"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user