From 9e3fb5cf166d28ec2f060b85acd10c897be9f29b Mon Sep 17 00:00:00 2001 From: nrslib <38722970+nrslib@users.noreply.github.com> Date: Sun, 22 Feb 2026 02:47:11 +0900 Subject: [PATCH] fix: validate override piece via resolver including ensemble scope --- src/__tests__/selectAndExecute-autoPr.test.ts | 11 +++++++++++ src/features/tasks/execute/selectAndExecute.ts | 8 +++----- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/__tests__/selectAndExecute-autoPr.test.ts b/src/__tests__/selectAndExecute-autoPr.test.ts index 4dd60a7..f66243b 100644 --- a/src/__tests__/selectAndExecute-autoPr.test.ts +++ b/src/__tests__/selectAndExecute-autoPr.test.ts @@ -33,6 +33,7 @@ vi.mock('../infra/config/index.js', () => ({ resolvePieceConfigValue: (...args: unknown[]) => mockResolvePieceConfigValue(...args), listPieces: vi.fn(() => ['default']), listPieceEntries: vi.fn(() => []), + loadPieceByIdentifier: vi.fn((identifier: string) => (identifier === 'default' ? { name: 'default' } : null)), isPiecePath: vi.fn(() => false), })); @@ -86,11 +87,13 @@ vi.mock('../features/pieceSelection/index.js', () => ({ })); import { confirm } from '../shared/prompt/index.js'; +import { loadPieceByIdentifier } from '../infra/config/index.js'; import { createSharedClone, autoCommitAndPush, summarizeTaskName } from '../infra/task/index.js'; import { selectPiece } from '../features/pieceSelection/index.js'; import { selectAndExecuteTask, determinePiece } from '../features/tasks/execute/selectAndExecute.js'; const mockConfirm = vi.mocked(confirm); +const mockLoadPieceByIdentifier = vi.mocked(loadPieceByIdentifier); const mockCreateSharedClone = vi.mocked(createSharedClone); const mockAutoCommitAndPush = vi.mocked(autoCommitAndPush); const mockSummarizeTaskName = vi.mocked(summarizeTaskName); @@ -180,6 +183,14 @@ describe('resolveAutoPr default in selectAndExecuteTask', () => { expect(mockSelectPiece).toHaveBeenCalledWith('/project'); }); + it('should accept ensemble scoped piece override when it exists', async () => { + mockLoadPieceByIdentifier.mockReturnValueOnce({ name: '@nrslib/takt-packages/critical-thinking' } as never); + + const selected = await determinePiece('/project', '@nrslib/takt-packages/critical-thinking'); + + expect(selected).toBe('@nrslib/takt-packages/critical-thinking'); + }); + it('should fail task record when executeTask throws', async () => { mockConfirm.mockResolvedValue(true); mockSummarizeTaskName.mockResolvedValue('test-task'); diff --git a/src/features/tasks/execute/selectAndExecute.ts b/src/features/tasks/execute/selectAndExecute.ts index ab22c09..c717593 100644 --- a/src/features/tasks/execute/selectAndExecute.ts +++ b/src/features/tasks/execute/selectAndExecute.ts @@ -7,12 +7,11 @@ */ import { - listPieces, + loadPieceByIdentifier, isPiecePath, } from '../../../infra/config/index.js'; import { confirm } from '../../../shared/prompt/index.js'; import { createSharedClone, summarizeTaskName, getCurrentBranch, TaskRunner } from '../../../infra/task/index.js'; -import { DEFAULT_PIECE_NAME } from '../../../shared/constants.js'; import { info, error, withProgress } from '../../../shared/ui/index.js'; import { createLogger } from '../../../shared/utils/index.js'; import { executeTask } from './taskExecution.js'; @@ -30,9 +29,8 @@ export async function determinePiece(cwd: string, override?: string): Promise