From 184a1d756a7a01842bca75e01ab2d6b2a930bb9a Mon Sep 17 00:00:00 2001 From: nrslib <38722970+nrslib@users.noreply.github.com> Date: Tue, 3 Feb 2026 19:18:51 +0900 Subject: [PATCH] =?UTF-8?q?=E4=BC=9A=E8=A9=B1=E5=86=85=E5=AE=B9=E3=81=8B?= =?UTF-8?q?=E3=82=89=E3=82=BF=E3=82=B9=E3=82=AF=E8=A6=81=E4=BB=B6=E3=82=92?= =?UTF-8?q?=E3=81=BE=E3=81=A8=E3=82=81=E3=82=8B=E5=BF=85=E8=A6=81=E3=81=8C?= =?UTF-8?q?=E3=81=AA=E3=81=8F=E3=81=AA=E3=81=A3=E3=81=9F=E3=81=AE=E3=81=A7?= =?UTF-8?q?=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/__tests__/addTask.test.ts | 74 ++---------------------------- src/__tests__/prompts.test.ts | 2 - src/features/tasks/add/index.ts | 29 +----------- src/features/tasks/index.ts | 2 +- src/shared/prompts/prompts_en.yaml | 6 --- src/shared/prompts/prompts_ja.yaml | 6 --- 6 files changed, 8 insertions(+), 111 deletions(-) diff --git a/src/__tests__/addTask.test.ts b/src/__tests__/addTask.test.ts index eaf33f2..84fe063 100644 --- a/src/__tests__/addTask.test.ts +++ b/src/__tests__/addTask.test.ts @@ -69,45 +69,33 @@ vi.mock('../infra/github/issue.js', () => ({ })); import { interactiveMode } from '../features/interactive/index.js'; -import { getProvider } from '../infra/providers/index.js'; import { promptInput, confirm } from '../shared/prompt/index.js'; import { summarizeTaskName } from '../infra/task/summarize.js'; import { determineWorkflow } from '../features/tasks/execute/selectAndExecute.js'; import { getWorkflowDescription } from '../infra/config/loaders/workflowResolver.js'; import { resolveIssueTask } from '../infra/github/issue.js'; -import { addTask, summarizeConversation } from '../features/tasks/index.js'; +import { addTask } from '../features/tasks/index.js'; const mockResolveIssueTask = vi.mocked(resolveIssueTask); - const mockInteractiveMode = vi.mocked(interactiveMode); -const mockGetProvider = vi.mocked(getProvider); const mockPromptInput = vi.mocked(promptInput); const mockConfirm = vi.mocked(confirm); const mockSummarizeTaskName = vi.mocked(summarizeTaskName); const mockDetermineWorkflow = vi.mocked(determineWorkflow); const mockGetWorkflowDescription = vi.mocked(getWorkflowDescription); -/** Helper: set up mocks for the full happy path */ function setupFullFlowMocks(overrides?: { - conversationTask?: string; - summaryContent?: string; + task?: string; slug?: string; }) { - const task = overrides?.conversationTask ?? 'User: 認証機能を追加したい\n\nAssistant: 了解です。'; - const summary = overrides?.summaryContent ?? '# 認証機能追加\nJWT認証を実装する'; + const task = overrides?.task ?? '# 認証機能追加\nJWT認証を実装する'; const slug = overrides?.slug ?? 'add-auth'; mockDetermineWorkflow.mockResolvedValue('default'); mockGetWorkflowDescription.mockReturnValue({ name: 'default', description: '' }); mockInteractiveMode.mockResolvedValue({ confirmed: true, task }); - - const mockProviderCall = vi.fn().mockResolvedValue({ content: summary }); - mockGetProvider.mockReturnValue({ call: mockProviderCall } as any); - mockSummarizeTaskName.mockResolvedValue(slug); mockConfirm.mockResolvedValue(false); - - return { mockProviderCall }; } let testDir: string; @@ -135,11 +123,9 @@ describe('addTask', () => { // When await addTask(testDir); - // Then: no task file created const tasksDir = path.join(testDir, '.takt', 'tasks'); const files = fs.existsSync(tasksDir) ? fs.readdirSync(tasksDir) : []; expect(files.length).toBe(0); - expect(mockGetProvider).not.toHaveBeenCalled(); expect(mockSummarizeTaskName).not.toHaveBeenCalled(); }); @@ -160,38 +146,14 @@ describe('addTask', () => { expect(content).toContain('JWT認証を実装する'); }); - it('should summarize conversation via provider.call', async () => { - // Given - const { mockProviderCall } = setupFullFlowMocks({ - conversationTask: 'User: バグ修正して\n\nAssistant: どのバグですか?', - }); - - // When - await addTask(testDir); - - // Then: provider.call was called with conversation text - expect(mockProviderCall).toHaveBeenCalledWith( - 'task-summarizer', - 'User: バグ修正して\n\nAssistant: どのバグですか?', - expect.objectContaining({ - cwd: testDir, - maxTurns: 1, - allowedTools: [], - }), - ); - }); - - it('should use first line of summary for filename generation', async () => { - // Given: summary with multiple lines + it('should use first line of task for filename generation', async () => { setupFullFlowMocks({ - summaryContent: 'First line summary\nSecond line details', + task: 'First line summary\nSecond line details', slug: 'first-line', }); - // When await addTask(testDir); - // Then: summarizeTaskName receives only the first line expect(mockSummarizeTaskName).toHaveBeenCalledWith('First line summary', { cwd: testDir }); }); @@ -354,11 +316,9 @@ describe('addTask', () => { // When await addTask(testDir, '#99'); - // Then: no task file created, no crash const tasksDir = path.join(testDir, '.takt', 'tasks'); const files = fs.readdirSync(tasksDir); expect(files.length).toBe(0); - expect(mockGetProvider).not.toHaveBeenCalled(); }); it('should include issue number in task file when issue reference is used', async () => { @@ -378,27 +338,3 @@ describe('addTask', () => { expect(content).toContain('issue: 99'); }); }); - -describe('summarizeConversation', () => { - it('should call provider with summarize system prompt', async () => { - // Given - const mockCall = vi.fn().mockResolvedValue({ content: 'Summary text' }); - mockGetProvider.mockReturnValue({ call: mockCall } as any); - - // When - const result = await summarizeConversation('/project', 'conversation text'); - - // Then - expect(result).toBe('Summary text'); - expect(mockCall).toHaveBeenCalledWith( - 'task-summarizer', - 'conversation text', - expect.objectContaining({ - cwd: '/project', - maxTurns: 1, - allowedTools: [], - systemPrompt: expect.stringContaining('会話履歴からタスクの要件をまとめてください'), - }), - ); - }); -}); diff --git a/src/__tests__/prompts.test.ts b/src/__tests__/prompts.test.ts index 44827b3..4e6b752 100644 --- a/src/__tests__/prompts.test.ts +++ b/src/__tests__/prompts.test.ts @@ -105,7 +105,6 @@ describe('YAML content integrity', () => { expect(() => getPrompt('interactive.noTranscript', 'en')).not.toThrow(); expect(() => getPromptObject('interactive.ui', 'en')).not.toThrow(); expect(() => getPrompt('summarize.slugGenerator')).not.toThrow(); - expect(() => getPrompt('summarize.conversationSummarizer')).not.toThrow(); expect(() => getPrompt('claude.agentDefault')).not.toThrow(); expect(() => getPrompt('claude.judgePrompt')).not.toThrow(); expect(() => getPromptObject('instruction.metadata', 'en')).not.toThrow(); @@ -126,7 +125,6 @@ describe('YAML content integrity', () => { expect(() => getPrompt('interactive.noTranscript', 'ja')).not.toThrow(); expect(() => getPromptObject('interactive.ui', 'ja')).not.toThrow(); expect(() => getPrompt('summarize.slugGenerator', 'ja')).not.toThrow(); - expect(() => getPrompt('summarize.conversationSummarizer', 'ja')).not.toThrow(); expect(() => getPrompt('claude.agentDefault', 'ja')).not.toThrow(); expect(() => getPrompt('claude.judgePrompt', 'ja')).not.toThrow(); expect(() => getPromptObject('instruction.metadata', 'ja')).not.toThrow(); diff --git a/src/features/tasks/add/index.ts b/src/features/tasks/add/index.ts index 52c320b..93d85d7 100644 --- a/src/features/tasks/add/index.ts +++ b/src/features/tasks/add/index.ts @@ -13,37 +13,12 @@ import { success, info } from '../../../shared/ui/index.js'; import { summarizeTaskName, type TaskFileData } from '../../../infra/task/index.js'; import { loadGlobalConfig, getWorkflowDescription } from '../../../infra/config/index.js'; import { determineWorkflow } from '../execute/selectAndExecute.js'; -import { getProvider, type ProviderType } from '../../../infra/providers/index.js'; import { createLogger, getErrorMessage } from '../../../shared/utils/index.js'; -import { getPrompt } from '../../../shared/prompts/index.js'; import { isIssueReference, resolveIssueTask, parseIssueNumbers } from '../../../infra/github/index.js'; import { interactiveMode } from '../../interactive/index.js'; const log = createLogger('add-task'); -/** - * Summarize conversation history into a task description using AI. - */ -export async function summarizeConversation(cwd: string, conversationText: string): Promise { - const globalConfig = loadGlobalConfig(); - const providerType = (globalConfig.provider as ProviderType) ?? 'claude'; - const provider = getProvider(providerType); - - info('Summarizing task from conversation...'); - - const response = await provider.call('task-summarizer', conversationText, { - cwd, - maxTurns: 1, - allowedTools: [], - systemPrompt: getPrompt('summarize.conversationSummarizer'), - }); - - return response.content; -} - -/** - * Generate a unique task filename with AI-summarized slug - */ async function generateFilename(tasksDir: string, taskContent: string, cwd: string): Promise { info('Generating task filename...'); const slug = await summarizeTaskName(taskContent, { cwd }); @@ -112,8 +87,8 @@ export async function addTask(cwd: string, task?: string): Promise { return; } - // 会話履歴からタスク要約を生成 - taskContent = await summarizeConversation(cwd, result.task); + // interactiveMode already returns a summarized task from conversation + taskContent = result.task; } // 3. 要約からファイル名生成 diff --git a/src/features/tasks/index.ts b/src/features/tasks/index.ts index 020eedc..0aa0f78 100644 --- a/src/features/tasks/index.ts +++ b/src/features/tasks/index.ts @@ -14,7 +14,7 @@ export { type SelectAndExecuteOptions, type WorktreeConfirmationResult, } from './execute/selectAndExecute.js'; -export { addTask, summarizeConversation } from './add/index.js'; +export { addTask } from './add/index.js'; export { watchTasks } from './watch/index.js'; export { listTasks, diff --git a/src/shared/prompts/prompts_en.yaml b/src/shared/prompts/prompts_en.yaml index 39ec3ae..e1a22b2 100644 --- a/src/shared/prompts/prompts_en.yaml +++ b/src/shared/prompts/prompts_en.yaml @@ -96,12 +96,6 @@ summarize: worktreeを作るときブランチ名をAIで生成 → ai-branch-naming レビュー画面に元の指示を表示する → show-original-instruction - conversationSummarizer: | - 会話履歴からタスクの要件をまとめてください。 - タスク実行エージェントへの指示として使われます。 - 具体的・簡潔に、必要な情報をすべて含めてください。 - マークダウン形式で出力してください。 - # ===== Claude Client ===== claude: agentDefault: "You are the {agentName} agent. Follow the standard {agentName} workflow." diff --git a/src/shared/prompts/prompts_ja.yaml b/src/shared/prompts/prompts_ja.yaml index 8f70a28..db0053c 100644 --- a/src/shared/prompts/prompts_ja.yaml +++ b/src/shared/prompts/prompts_ja.yaml @@ -109,12 +109,6 @@ summarize: worktreeを作るときブランチ名をAIで生成 → ai-branch-naming レビュー画面に元の指示を表示する → show-original-instruction - conversationSummarizer: | - 会話履歴からタスクの要件をまとめてください。 - タスク実行エージェントへの指示として使われます。 - 具体的・簡潔に、必要な情報をすべて含めてください。 - マークダウン形式で出力してください。 - # ===== Claude Client ===== claude: agentDefault: "You are the {agentName} agent. Follow the standard {agentName} workflow."