fix: retryコマンドの有効範囲と案内文を修正

This commit is contained in:
nrslib 2026-02-19 23:24:13 +09:00
parent e70bceb4a8
commit 2926785c2c
6 changed files with 43 additions and 11 deletions

View File

@ -77,6 +77,8 @@ vi.mock('../shared/i18n/index.js', () => ({
proposed: 'Proposed:',
actionPrompt: 'What next?',
playNoTask: 'No task for /play',
retryNoOrder: 'No previous order found.',
retryUnavailable: '/retry is not available in this mode.',
cancelled: 'Cancelled',
actions: { execute: 'Execute', saveTask: 'Save', continue: 'Continue' },
})),
@ -212,4 +214,15 @@ describe('/resume command', () => {
expect(capture.sessionIds[0]).toBe('resumed-session-xyz');
expect(result.action).toBe('cancel');
});
it('should reject /retry in non-retry mode', async () => {
setupRawStdin(toRawInputs(['/retry', '/cancel']));
setupProvider([]);
const ctx = createSessionContext();
const result = await runConversationLoop('/test', ctx, defaultStrategy, undefined, undefined);
expect(mockLogInfo).toHaveBeenCalledWith('/retry is not available in this mode.');
expect(result.action).toBe('cancel');
});
});

View File

@ -85,6 +85,8 @@ export interface ConversationStrategy {
selectAction?: (task: string, lang: 'en' | 'ja') => Promise<PostSummaryAction | null>;
/** Previous order.md content for /replay command (retry/instruct only) */
previousOrderContent?: string;
/** Enable /retry slash command (retry mode only) */
enableRetryCommand?: boolean;
}
/**
@ -166,6 +168,10 @@ export async function runConversationLoop(
}
if (trimmed === '/retry') {
if (!strategy.enableRetryCommand) {
info(ui.retryUnavailable);
continue;
}
if (!strategy.previousOrderContent) {
info(ui.retryNoOrder);
continue;

View File

@ -46,6 +46,7 @@ export interface InteractiveUIText {
cancelled: string;
playNoTask: string;
retryNoOrder: string;
retryUnavailable: string;
}
/**

View File

@ -14,13 +14,12 @@ import {
} from './conversationLoop.js';
import {
createSelectActionWithoutExecute,
buildReplayHint,
formatMovementPreviews,
type PieceContext,
} from './interactive-summary.js';
import { resolveLanguage } from './interactive.js';
import { loadTemplate } from '../../shared/prompts/index.js';
import { getLabelObject } from '../../shared/i18n/index.js';
import { getLabel, getLabelObject } from '../../shared/i18n/index.js';
import { resolveConfigValues } from '../../infra/config/index.js';
import type { InstructModeResult, InstructUIText } from '../tasks/list/instructMode.js';
@ -120,10 +119,10 @@ export async function runRetryMode(
const templateVars = buildRetryTemplateVars(retryContext, lang, previousOrderContent);
const systemPrompt = loadTemplate('score_retry_system_prompt', ctx.lang, templateVars);
const replayHint = buildReplayHint(ctx.lang, previousOrderContent !== null);
const retryIntro = getLabel('retry.ui.intro', ctx.lang);
const introLabel = ctx.lang === 'ja'
? `## リトライ: ${retryContext.failure.taskName}\n\nブランチ: ${retryContext.branchName}\n\n${ui.intro}${replayHint}`
: `## Retry: ${retryContext.failure.taskName}\n\nBranch: ${retryContext.branchName}\n\n${ui.intro}${replayHint}`;
? `## リトライ: ${retryContext.failure.taskName}\n\nブランチ: ${retryContext.branchName}\n\n${retryIntro}`
: `## Retry: ${retryContext.failure.taskName}\n\nBranch: ${retryContext.branchName}\n\n${retryIntro}`;
const policyContent = loadTemplate('score_interactive_policy', ctx.lang, {});
@ -144,6 +143,7 @@ export async function runRetryMode(
introMessage: introLabel,
selectAction: createSelectActionWithoutExecute(ui),
previousOrderContent: previousOrderContent ?? undefined,
enableRetryCommand: true,
};
const result = await runConversationLoop(cwd, ctx, strategy, retryContext.pieceContext, undefined);

View File

@ -10,7 +10,7 @@ interactive:
conversationLabel: "Conversation:"
noTranscript: "(No local transcript. Summarize the current session context.)"
ui:
intro: "Interactive mode - describe your task. Commands: /go (execute), /play (run now), /resume (load session), /retry (rerun previous order), /cancel (exit)"
intro: "Interactive mode - describe your task. Commands: /go (create instruction & run), /play (run now), /resume (load session), /cancel (exit)"
resume: "Resuming previous session"
noConversation: "No conversation yet. Please describe your task first."
summarizeFailed: "Failed to summarize conversation. Please try again."
@ -25,6 +25,7 @@ interactive:
cancelled: "Cancelled"
playNoTask: "Please specify task content: /play <task>"
retryNoOrder: "No previous order (order.md) found. /retry is only available during retry."
retryUnavailable: "/retry is only available in Retry mode from `takt list`."
personaFallback: "No persona available for the first movement. Falling back to assistant mode."
modeSelection:
prompt: "Select interactive mode:"
@ -77,10 +78,10 @@ piece:
# ===== Instruct Mode UI (takt list -> instruct) =====
instruct:
ui:
intro: "Instruct mode - describe additional instructions. Commands: /go (summarize), /retry (rerun previous order), /cancel (exit)"
intro: "Instruct mode - describe additional instructions. Commands: /go (create instruction & run), /replay (resubmit previous order), /cancel (exit)"
resume: "Resuming previous session"
noConversation: "No conversation yet. Please describe your instructions first."
summarizeFailed: "Failed to summarize conversation. Please try again."
summarizeFailed: "Failed to create instruction. Please try again."
continuePrompt: "Okay, continue describing your instructions."
proposed: "Proposed additional instructions:"
actionPrompt: "What would you like to do?"
@ -91,6 +92,11 @@ instruct:
cancelled: "Cancelled"
replayNoOrder: "Previous order (order.md) not found"
# ===== Retry Mode UI (takt list -> retry) =====
retry:
ui:
intro: "Retry mode - describe additional instructions. Commands: /go (create instruction & run), /retry (rerun previous order), /cancel (exit)"
run:
notifyComplete: "Run complete ({total} tasks)"
notifyAbort: "Run finished with errors ({failed})"

View File

@ -10,7 +10,7 @@ interactive:
conversationLabel: "会話:"
noTranscript: "(ローカル履歴なし。現在のセッション文脈を要約してください。)"
ui:
intro: "対話モード - タスク内容を入力してください。コマンド: /go実行), /play即実行, /resumeセッション読込, /retry前回の指示書で再実行, /cancel終了"
intro: "対話モード - タスク内容を入力してください。コマンド: /go指示書作成・実行), /play即実行, /resumeセッション読込, /cancel終了"
resume: "前回のセッションを再開します"
noConversation: "まだ会話がありません。まずタスク内容を入力してください。"
summarizeFailed: "会話の要約に失敗しました。再度お試しください。"
@ -25,6 +25,7 @@ interactive:
cancelled: "キャンセルしました"
playNoTask: "タスク内容を指定してください: /play <タスク内容>"
retryNoOrder: "前回の指示書order.mdが見つかりません。/retry はリトライ時のみ使用できます。"
retryUnavailable: "/retry は `takt list` の Retry モードでのみ使用できます。"
personaFallback: "先頭ムーブメントにペルソナがありません。アシスタントモードにフォールバックします。"
modeSelection:
prompt: "対話モードを選択してください:"
@ -77,10 +78,10 @@ piece:
# ===== Instruct Mode UI (takt list -> instruct) =====
instruct:
ui:
intro: "指示モード - 追加指示を入力してください。コマンド: /go要約), /retry前回の指示書で再実行, /cancel終了"
intro: "指示モード - 追加指示を入力してください。コマンド: /go指示書作成・実行), /replay前回の指示書で再投入, /cancel終了"
resume: "前回のセッションを再開します"
noConversation: "まだ会話がありません。まず追加指示を入力してください。"
summarizeFailed: "会話の要約に失敗しました。再度お試しください。"
summarizeFailed: "指示書の作成に失敗しました。再度お試しください。"
continuePrompt: "続けて追加指示を入力してください。"
proposed: "提案された追加指示:"
actionPrompt: "どうしますか?"
@ -91,6 +92,11 @@ instruct:
cancelled: "キャンセルしました"
replayNoOrder: "前回の指示書order.mdが見つかりません"
# ===== Retry Mode UI (takt list -> retry) =====
retry:
ui:
intro: "リトライモード - 追加指示を入力してください。コマンド: /go指示書作成・実行, /retry前回の指示書で再実行, /cancel終了"
run:
notifyComplete: "run完了 ({total} tasks)"
notifyAbort: "runはエラー終了 ({failed})"