From 36e77ae0fac7843b8c6630e1b93455c81868be92 Mon Sep 17 00:00:00 2001 From: nrs <38722970+nrslib@users.noreply.github.com> Date: Wed, 11 Feb 2026 06:37:06 +0900 Subject: [PATCH] takt: issue (#220) --- src/__tests__/parallel-logger.test.ts | 57 ++++++++++++++++++++++++ src/core/piece/engine/parallel-logger.ts | 20 +++++++-- 2 files changed, 74 insertions(+), 3 deletions(-) diff --git a/src/__tests__/parallel-logger.test.ts b/src/__tests__/parallel-logger.test.ts index 8f87bd8..67681b7 100644 --- a/src/__tests__/parallel-logger.test.ts +++ b/src/__tests__/parallel-logger.test.ts @@ -393,6 +393,63 @@ describe('ParallelLogger', () => { expect(doneIndex0).toBe(doneIndex1); }); + it('should prepend task prefix to all summary lines in rich mode', () => { + const logger = new ParallelLogger({ + subMovementNames: ['arch-review', 'security-review'], + writeFn, + progressInfo: { iteration: 5, maxMovements: 30 }, + taskLabel: 'override-persona-provider', + taskColorIndex: 0, + parentMovementName: 'reviewers', + movementIteration: 1, + }); + + logger.printSummary('reviewers', [ + { name: 'arch-review', condition: 'approved' }, + { name: 'security-review', condition: 'needs_fix' }, + ]); + + // Every output line should have the task prefix + for (const line of output) { + expect(line).toContain('[over]'); + expect(line).toContain('[reviewers]'); + expect(line).toContain('(5/30)(1)'); + } + + // Verify task color (cyan for index 0) + expect(output[0]).toContain('\x1b[36m'); + + // Verify summary content is still present + const fullOutput = output.join(''); + expect(fullOutput).toContain('reviewers results'); + expect(fullOutput).toContain('arch-review:'); + expect(fullOutput).toContain('approved'); + expect(fullOutput).toContain('security-review:'); + expect(fullOutput).toContain('needs_fix'); + }); + + it('should not prepend task prefix to summary lines in non-rich mode', () => { + const logger = new ParallelLogger({ + subMovementNames: ['arch-review'], + writeFn, + }); + + logger.printSummary('reviewers', [ + { name: 'arch-review', condition: 'approved' }, + ]); + + // No task prefix should appear + for (const line of output) { + expect(line).not.toContain('[over]'); + } + + // Summary content is present + const fullOutput = output.join(''); + expect(fullOutput).toContain('reviewers results'); + expect(fullOutput).toContain('arch-review:'); + expect(fullOutput).toContain('approved'); + }); + it('should flush remaining buffers before printing summary', () => { const logger = new ParallelLogger({ subMovementNames: ['step-a'], diff --git a/src/core/piece/engine/parallel-logger.ts b/src/core/piece/engine/parallel-logger.ts index 2566a2a..d44a6ff 100644 --- a/src/core/piece/engine/parallel-logger.ts +++ b/src/core/piece/engine/parallel-logger.ts @@ -189,6 +189,19 @@ export class ParallelLogger { } } + /** + * Build the prefix string for summary lines (no sub-movement name). + * Returns empty string in non-rich mode (no task-level prefix needed). + */ + private buildSummaryPrefix(): string { + if (this.taskLabel && this.parentMovementName && this.progressInfo && this.movementIteration != null && this.taskColorIndex != null) { + const taskColor = COLORS[this.taskColorIndex % COLORS.length]; + const { iteration, maxMovements } = this.progressInfo; + return `${taskColor}[${this.taskLabel}]${RESET}[${this.parentMovementName}](${iteration}/${maxMovements})(${this.movementIteration}) `; + } + return ''; + } + /** * Flush remaining line buffers for all sub-movements. * Call after all sub-movements complete to output any trailing partial lines. @@ -243,10 +256,11 @@ export class ParallelLogger { const headerLine = `${'─'.repeat(sideWidth)}${headerText}${'─'.repeat(sideWidth)}`; const footerLine = '─'.repeat(headerLine.length); - this.writeFn(`${headerLine}\n`); + const summaryPrefix = this.buildSummaryPrefix(); + this.writeFn(`${summaryPrefix}${headerLine}\n`); for (const line of resultLines) { - this.writeFn(`${line}\n`); + this.writeFn(`${summaryPrefix}${line}\n`); } - this.writeFn(`${footerLine}\n`); + this.writeFn(`${summaryPrefix}${footerLine}\n`); } }