From 54fc67e283e03941a47e50db2624eb792a993f30 Mon Sep 17 00:00:00 2001 From: Eyejoker Date: Mon, 30 Mar 2026 03:55:58 +0900 Subject: [PATCH] test: align prompt and scheduler expectations --- src/agent-runner-environment.test.ts | 41 +++--------------------- src/platform-prompts.test.ts | 13 ++++---- src/task-scheduler.test.ts | 47 +++++++++++++++++++++++----- 3 files changed, 51 insertions(+), 50 deletions(-) diff --git a/src/agent-runner-environment.test.ts b/src/agent-runner-environment.test.ts index e649fd3..4f5b32f 100644 --- a/src/agent-runner-environment.test.ts +++ b/src/agent-runner-environment.test.ts @@ -199,7 +199,7 @@ describe('prepareGroupEnvironment codex auth handling', () => { expect(auth).toEqual(rotatedAuth); }); - it('uses the failover prompt pack for codex-review when it owns an explicit failover lease', () => { + it('uses the failover owner prompt pack for codex-review when it owns an explicit failover lease', () => { vi.mocked(config.isReviewService).mockReturnValue(true); vi.mocked(db.isPairedRoomJid).mockReturnValue(true); vi.mocked(serviceRouting.getEffectiveChannelLease).mockReturnValue({ @@ -218,10 +218,6 @@ describe('prepareGroupEnvironment codex auth handling', () => { path.join(promptsDir, 'codex-review-platform.md'), 'review platform prompt\n', ); - fs.writeFileSync( - path.join(promptsDir, 'codex-review-paired-room.md'), - 'review paired prompt\n', - ); fs.writeFileSync( path.join(promptsDir, 'owner-common-platform.md'), 'owner common platform prompt\n', @@ -234,11 +230,6 @@ describe('prepareGroupEnvironment codex auth handling', () => { path.join(promptsDir, 'codex-review-failover-platform.md'), 'failover platform prompt\n', ); - fs.writeFileSync( - path.join(promptsDir, 'codex-review-failover-paired-room.md'), - 'failover paired prompt\n', - ); - prepareGroupEnvironment( { ...group, workDir: path.join(tempRoot, 'workdir') }, false, @@ -264,12 +255,11 @@ describe('prepareGroupEnvironment codex auth handling', () => { 'owner common platform prompt', 'failover platform prompt', 'owner common paired prompt', - 'failover paired prompt', 'memory briefing', ]); }); - it('adds the shared owner prompt fragments to Claude session prompts', () => { + it('adds only the shared owner prompt fragments to Claude session prompts', () => { vi.mocked(db.isPairedRoomJid).mockReturnValue(true); mockReadEnvFile.mockReturnValue({}); @@ -309,12 +299,11 @@ describe('prepareGroupEnvironment codex auth handling', () => { 'owner common platform prompt', 'platform prompt', 'owner common paired prompt', - 'paired room prompt', 'memory briefing', ]); }); - it('returns to the normal review prompt stack after failover is cleared', () => { + it('returns to the normal owner prompt stack after failover is cleared', () => { vi.mocked(config.isReviewService).mockReturnValue(true); vi.mocked(db.isPairedRoomJid).mockReturnValue(true); vi.mocked(serviceRouting.getEffectiveChannelLease).mockReturnValue({ @@ -329,23 +318,6 @@ describe('prepareGroupEnvironment codex auth handling', () => { const promptsDir = path.join(tempRoot, 'prompts'); fs.mkdirSync(promptsDir, { recursive: true }); - fs.writeFileSync( - path.join(promptsDir, 'codex-review-platform.md'), - 'review platform prompt\n', - ); - fs.writeFileSync( - path.join(promptsDir, 'codex-review-paired-room.md'), - 'review paired prompt\n', - ); - fs.writeFileSync( - path.join(promptsDir, 'codex-review-failover-platform.md'), - 'failover platform prompt\n', - ); - fs.writeFileSync( - path.join(promptsDir, 'codex-review-failover-paired-room.md'), - 'failover paired prompt\n', - ); - prepareGroupEnvironment(group, false, 'dc:test'); const agentsPath = path.join( @@ -360,11 +332,6 @@ describe('prepareGroupEnvironment codex auth handling', () => { const agents = fs.readFileSync(agentsPath, 'utf-8'); const segments = agents.trim().split('\n\n---\n\n'); - expect(segments).toEqual([ - 'platform prompt', - 'review platform prompt', - 'paired room prompt', - 'review paired prompt', - ]); + expect(segments).toEqual(['platform prompt']); }); }); diff --git a/src/platform-prompts.test.ts b/src/platform-prompts.test.ts index d0f3719..6ac4919 100644 --- a/src/platform-prompts.test.ts +++ b/src/platform-prompts.test.ts @@ -57,18 +57,19 @@ describe('platform-prompts', () => { expect(readPairedRoomPrompt('claude-code')).toBe('Claude paired prompt'); }); - it('keeps codex approval wording role-based while preserving failover identity wording', () => { + it('maps Codex paired-room prompts to the shared reviewer prompt while preserving failover identity wording', () => { const repoRoot = path.resolve( path.dirname(fileURLToPath(import.meta.url)), '..', ); - const codexPairedPrompt = fs.readFileSync( - path.join(repoRoot, 'prompts', 'codex-paired-room.md'), - 'utf-8', + expect(getPairedRoomPromptPath('codex', repoRoot)).toBe( + path.join(repoRoot, 'prompts', 'claude-paired-room.md'), ); - expect(codexPairedPrompt).toContain('owner-side paired agent'); - expect(codexPairedPrompt).not.toContain("Claude's review or test plan"); + + const codexPairedPrompt = readPairedRoomPrompt('codex', repoRoot); + expect(codexPairedPrompt).toContain('reviewer'); + expect(codexPairedPrompt).not.toContain('owner-side paired agent'); const failoverPlatformPrompt = fs.readFileSync( path.join(repoRoot, 'prompts', 'codex-review-failover-platform.md'), diff --git a/src/task-scheduler.test.ts b/src/task-scheduler.test.ts index f262ac6..4045a3f 100644 --- a/src/task-scheduler.test.ts +++ b/src/task-scheduler.test.ts @@ -131,6 +131,7 @@ vi.mock('./github-ci.js', () => ({ import { _initTestDatabase, createTask, getTaskById } from './db.js'; import * as codexTokenRotation from './codex-token-rotation.js'; +import { TIMEZONE } from './config.js'; import { createTaskStatusTracker } from './task-status-tracker.js'; import { TASK_STATUS_MESSAGE_PREFIX } from './task-watch-status.js'; import * as tokenRotation from './token-rotation.js'; @@ -144,6 +145,19 @@ import { startSchedulerLoop, } from './task-scheduler.js'; +function formatExpectedTimeLabel(timestampIso: string): string { + return new Intl.DateTimeFormat('ko-KR', { + hour: '2-digit', + minute: '2-digit', + second: '2-digit', + hour12: false, + timeZone: TIMEZONE, + }) + .format(new Date(timestampIso)) + .replace(/:/g, '시 ') + .replace(/시 (\d{2})$/, '분 $1초'); +} + describe('task scheduler', () => { beforeEach(() => { _initTestDatabase(); @@ -206,7 +220,7 @@ describe('task scheduler', () => { expect(task?.status).toBe('paused'); }); - it('only enqueues tasks owned by the current service agent type', async () => { + it('enqueues due tasks across agent types in unified service mode', async () => { const dueAt = new Date(Date.now() - 60_000).toISOString(); createTask({ id: 'task-claude', @@ -256,9 +270,17 @@ describe('task scheduler', () => { await vi.advanceTimersByTimeAsync(10); - expect(enqueueTask).toHaveBeenCalledTimes(1); - expect(enqueueTask.mock.calls[0][0]).toBe('shared@g.us::task:task-codex'); - expect(enqueueTask.mock.calls[0][1]).toBe('task-codex'); + expect(enqueueTask).toHaveBeenCalledTimes(2); + expect( + enqueueTask.mock.calls + .map(([queueJid, taskId]) => `${queueJid}|${taskId}`) + .sort(), + ).toEqual( + [ + 'shared@g.us::task:task-claude|task-claude', + 'shared@g.us::task:task-codex|task-codex', + ].sort(), + ); }); it('keeps group-context tasks on the chat queue key', async () => { @@ -1348,12 +1370,19 @@ Check the run. nextRun: '2026-03-19T07:04:10.000Z', }); + const expectedCheckedLabel = formatExpectedTimeLabel( + '2026-03-19T07:02:10.000Z', + ); + const expectedNextLabel = formatExpectedTimeLabel( + '2026-03-19T07:04:10.000Z', + ); + expect(rendered).toContain('CI 감시 중: GitHub Actions run 123456'); expect(rendered).toContain('- 상태: 대기 중'); - expect(rendered).toContain('- 마지막 확인: 16시 02분 10초'); + expect(rendered).toContain(`- 마지막 확인: ${expectedCheckedLabel}`); expect(rendered).toContain('- 경과 시간: 2분 10초'); expect(rendered).toContain('- 확인 간격: 1분'); - expect(rendered).toContain('- 다음 확인: 16시 04분 10초'); + expect(rendered).toContain(`- 다음 확인: ${expectedNextLabel}`); expect(rendered).not.toContain('16:02:10'); expect(rendered).not.toContain('16:04:10'); }); @@ -1429,6 +1458,10 @@ Check the run. vi.setSystemTime(new Date('2026-03-19T07:02:10.000Z')); await tracker.update('waiting', '2026-03-19T07:04:10.000Z'); + const expectedNextLabel = formatExpectedTimeLabel( + '2026-03-19T07:04:10.000Z', + ); + expect(editTrackedMessage).toHaveBeenCalledWith( 'shared@g.us', 'msg-123', @@ -1437,7 +1470,7 @@ Check the run. expect(editTrackedMessage).toHaveBeenCalledWith( 'shared@g.us', 'msg-123', - expect.stringContaining('- 다음 확인: 16시 04분 10초'), + expect.stringContaining(`- 다음 확인: ${expectedNextLabel}`), ); const secondState = getTaskById('task-watch-status');