From 35a59218d5cf4adcd05a65076bb8a790b5ab29b6 Mon Sep 17 00:00:00 2001 From: Eyejoker Date: Tue, 31 Mar 2026 22:27:17 +0900 Subject: [PATCH] refactor: internalize setRegisteredGroup export --- src/db.test.ts | 32 +++++++++++++-------------- src/db.ts | 18 ++++++++++++++-- src/duplicate-suppression.test.ts | 36 +++++++++++++++---------------- src/ipc-auth.test.ts | 10 ++++----- src/service-routing.test.ts | 24 ++++++++++----------- 5 files changed, 67 insertions(+), 53 deletions(-) diff --git a/src/db.test.ts b/src/db.test.ts index 330314b..de7487e 100644 --- a/src/db.test.ts +++ b/src/db.test.ts @@ -7,6 +7,7 @@ import { describe, it, expect, beforeEach } from 'vitest'; import { _initTestDatabase, _initTestDatabaseFromFile, + _setRegisteredGroupForTests, assignRoom, claimServiceHandoff, completeServiceHandoffAndAdvanceTargetCursor, @@ -43,7 +44,6 @@ import { markWorkItemDelivered, markWorkItemDeliveryRetry, setSession, - setRegisteredGroup, setRouterStateForService, setExplicitRoomMode, storeChatMetadata, @@ -720,7 +720,7 @@ describe('message query LIMIT', () => { describe('registered group isMain', () => { it('persists isMain=true through set/get round-trip', () => { - setRegisteredGroup('dc:main', { + _setRegisteredGroupForTests('dc:main', { name: 'Main Chat', folder: 'discord_main', trigger: '@Andy', @@ -736,7 +736,7 @@ describe('registered group isMain', () => { }); it('omits isMain for non-main groups', () => { - setRegisteredGroup('group@g.us', { + _setRegisteredGroupForTests('group@g.us', { name: 'Family Chat', folder: 'discord_family-chat', trigger: '@Andy', @@ -750,14 +750,14 @@ describe('registered group isMain', () => { }); it('filters duplicate jid registrations by agent type', () => { - setRegisteredGroup('dc:shared', { + _setRegisteredGroupForTests('dc:shared', { name: 'Shared Room', folder: 'shared-room', trigger: '@Andy', added_at: '2024-01-01T00:00:00.000Z', agentType: 'claude-code', }); - setRegisteredGroup('dc:shared', { + _setRegisteredGroupForTests('dc:shared', { name: 'Shared Room', folder: 'shared-room', trigger: '@Codex', @@ -828,14 +828,14 @@ describe('room assignment writes', () => { describe('paired room registration', () => { it('detects when both Claude and Codex are registered on the same jid', () => { - setRegisteredGroup('dc:123', { + _setRegisteredGroupForTests('dc:123', { name: 'Paired Room', folder: 'paired-room', trigger: '@Andy', added_at: '2024-01-01T00:00:00.000Z', agentType: 'claude-code', }); - setRegisteredGroup('dc:123', { + _setRegisteredGroupForTests('dc:123', { name: 'Paired Room', folder: 'paired-room', trigger: '@Codex', @@ -853,7 +853,7 @@ describe('paired room registration', () => { }); it('does not mark solo rooms as paired', () => { - setRegisteredGroup('dc:solo', { + _setRegisteredGroupForTests('dc:solo', { name: 'Solo Claude Room', folder: 'solo-claude', trigger: '@Andy', @@ -866,14 +866,14 @@ describe('paired room registration', () => { }); it('keeps inferred room mode available when no explicit override exists', () => { - setRegisteredGroup('dc:legacy-paired', { + _setRegisteredGroupForTests('dc:legacy-paired', { name: 'Legacy Paired', folder: 'legacy-paired', trigger: '@Andy', added_at: '2024-01-01T00:00:00.000Z', agentType: 'claude-code', }); - setRegisteredGroup('dc:legacy-paired', { + _setRegisteredGroupForTests('dc:legacy-paired', { name: 'Legacy Paired', folder: 'legacy-paired', trigger: '@Codex', @@ -966,14 +966,14 @@ describe('paired room registration', () => { }); it('keeps room-level metadata synced on setRegisteredGroup helper writes', () => { - setRegisteredGroup('dc:room-settings', { + _setRegisteredGroupForTests('dc:room-settings', { name: 'Room Settings Test', folder: 'room-settings-test', trigger: '@Claude', added_at: '2024-01-01T00:00:00.000Z', agentType: 'claude-code', }); - setRegisteredGroup('dc:room-settings', { + _setRegisteredGroupForTests('dc:room-settings', { name: 'Room Settings Test', folder: 'room-settings-test', trigger: '@Codex', @@ -1082,14 +1082,14 @@ describe('paired room registration', () => { }); it('lets explicit single override dual registration for paired-room checks', () => { - setRegisteredGroup('dc:explicit-single', { + _setRegisteredGroupForTests('dc:explicit-single', { name: 'Explicit Single', folder: 'explicit-single', trigger: '@Andy', added_at: '2024-01-01T00:00:00.000Z', agentType: 'claude-code', }); - setRegisteredGroup('dc:explicit-single', { + _setRegisteredGroupForTests('dc:explicit-single', { name: 'Explicit Single', folder: 'explicit-single', trigger: '@Codex', @@ -1105,7 +1105,7 @@ describe('paired room registration', () => { }); it('lets explicit tribunal become runnable when the configured reviewer can run on the solo registration', () => { - setRegisteredGroup('dc:explicit-tribunal', { + _setRegisteredGroupForTests('dc:explicit-tribunal', { name: 'Explicit Tribunal Claude', folder: 'explicit-tribunal-claude', trigger: '@Andy', @@ -1131,7 +1131,7 @@ describe('paired room registration', () => { }); it('keeps explicit tribunal non-runnable when the configured reviewer service is unavailable', () => { - setRegisteredGroup('dc:explicit-tribunal-codex', { + _setRegisteredGroupForTests('dc:explicit-tribunal-codex', { name: 'Explicit Tribunal Codex', folder: 'explicit-tribunal-codex', trigger: '@Codex', diff --git a/src/db.ts b/src/db.ts index d34428b..32ecf88 100644 --- a/src/db.ts +++ b/src/db.ts @@ -1987,7 +1987,10 @@ export function getRegisteredGroup( return getLegacyRegisteredGroup(db, jid, agentType); } -export function setRegisteredGroup(jid: string, group: RegisteredGroup): void { +function writeLegacyRegisteredGroupAndSyncRoomSettings( + jid: string, + group: RegisteredGroup, +): void { const existingRoomMode = getStoredRoomModeRow(jid); if (!isValidGroupFolder(group.folder)) { throw new Error(`Invalid group folder "${group.folder}" for JID ${jid}`); @@ -2017,6 +2020,17 @@ export function setRegisteredGroup(jid: string, group: RegisteredGroup): void { tx(); } +/** + * @internal Test/migration helper for seeding legacy capability rows. + * Runtime code must use assignRoom() so room_settings remains the explicit SSOT. + */ +export function _setRegisteredGroupForTests( + jid: string, + group: RegisteredGroup, +): void { + writeLegacyRegisteredGroupAndSyncRoomSettings(jid, group); +} + export function assignRoom( chatJid: string, input: AssignRoomInput, @@ -3337,7 +3351,7 @@ function migrateJsonState(): void { if (groups) { for (const [jid, group] of Object.entries(groups)) { try { - setRegisteredGroup(jid, group); + writeLegacyRegisteredGroupAndSyncRoomSettings(jid, group); } catch (err) { logger.warn( { jid, folder: group.folder, err }, diff --git a/src/duplicate-suppression.test.ts b/src/duplicate-suppression.test.ts index af938af..8552a9d 100644 --- a/src/duplicate-suppression.test.ts +++ b/src/duplicate-suppression.test.ts @@ -1,12 +1,12 @@ import { describe, it, expect, beforeEach, vi } from 'vitest'; import { + _setRegisteredGroupForTests, _initTestDatabase, storeMessage, storeChatMetadata, createProducedWorkItem, getOpenWorkItem, - setRegisteredGroup, getLastBotFinalMessage, markWorkItemDelivered, } from './db.js'; @@ -56,7 +56,7 @@ describe('hasReviewerLease', () => { it('returns true when both claude-code and codex are registered', () => { const jid = 'dc:paired-room'; - setRegisteredGroup(jid, { + _setRegisteredGroupForTests(jid, { name: 'Paired Room', folder: 'paired-room', trigger: '@claude', @@ -64,7 +64,7 @@ describe('hasReviewerLease', () => { agentType: 'claude-code', }); - setRegisteredGroup(jid, { + _setRegisteredGroupForTests(jid, { name: 'Paired Room', folder: 'paired-room', trigger: '@codex', @@ -78,7 +78,7 @@ describe('hasReviewerLease', () => { it('returns false when only claude-code is registered', () => { const jid = 'dc:single-claude'; - setRegisteredGroup(jid, { + _setRegisteredGroupForTests(jid, { name: 'Single Claude', folder: 'single-claude', trigger: '@claude', @@ -92,7 +92,7 @@ describe('hasReviewerLease', () => { it('returns false when only codex is registered', () => { const jid = 'dc:single-codex'; - setRegisteredGroup(jid, { + _setRegisteredGroupForTests(jid, { name: 'Single Codex', folder: 'single-codex', trigger: '@codex', @@ -180,7 +180,7 @@ describe('isDuplicateOfLastBotFinal (runtime function)', () => { setupChat(jid); // Register as paired room - setRegisteredGroup(jid, { + _setRegisteredGroupForTests(jid, { name: 'Paired Room', folder: 'paired-room', trigger: '@claude', @@ -188,7 +188,7 @@ describe('isDuplicateOfLastBotFinal (runtime function)', () => { agentType: 'claude-code', }); - setRegisteredGroup(jid, { + _setRegisteredGroupForTests(jid, { name: 'Paired Room', folder: 'paired-room', trigger: '@codex', @@ -225,7 +225,7 @@ describe('isDuplicateOfLastBotFinal (runtime function)', () => { setupChat(jid); // Register only one bot - setRegisteredGroup(jid, { + _setRegisteredGroupForTests(jid, { name: 'Single Bot', folder: 'single-bot', trigger: '@claude', @@ -257,7 +257,7 @@ describe('isDuplicateOfLastBotFinal (runtime function)', () => { setupChat(jid); // Register as paired room - setRegisteredGroup(jid, { + _setRegisteredGroupForTests(jid, { name: 'Paired Room', folder: 'paired-room', trigger: '@claude', @@ -265,7 +265,7 @@ describe('isDuplicateOfLastBotFinal (runtime function)', () => { agentType: 'claude-code', }); - setRegisteredGroup(jid, { + _setRegisteredGroupForTests(jid, { name: 'Paired Room', folder: 'paired-room', trigger: '@codex', @@ -297,7 +297,7 @@ describe('isDuplicateOfLastBotFinal (runtime function)', () => { setupChat(jid); // Register as paired room - setRegisteredGroup(jid, { + _setRegisteredGroupForTests(jid, { name: 'Paired Room', folder: 'paired-room', trigger: '@claude', @@ -305,7 +305,7 @@ describe('isDuplicateOfLastBotFinal (runtime function)', () => { agentType: 'claude-code', }); - setRegisteredGroup(jid, { + _setRegisteredGroupForTests(jid, { name: 'Paired Room', folder: 'paired-room', trigger: '@codex', @@ -336,7 +336,7 @@ describe('isDuplicateOfLastBotFinal (runtime function)', () => { setupChat(jid); // Register as paired room - setRegisteredGroup(jid, { + _setRegisteredGroupForTests(jid, { name: 'Paired Room', folder: 'paired-room', trigger: '@claude', @@ -344,7 +344,7 @@ describe('isDuplicateOfLastBotFinal (runtime function)', () => { agentType: 'claude-code', }); - setRegisteredGroup(jid, { + _setRegisteredGroupForTests(jid, { name: 'Paired Room', folder: 'paired-room', trigger: '@codex', @@ -384,7 +384,7 @@ describe('isDuplicateOfLastBotFinal (runtime function)', () => { setupChat(jid); // Register as paired room - setRegisteredGroup(jid, { + _setRegisteredGroupForTests(jid, { name: 'Paired Room', folder: 'paired-room', trigger: '@claude', @@ -392,7 +392,7 @@ describe('isDuplicateOfLastBotFinal (runtime function)', () => { agentType: 'claude-code', }); - setRegisteredGroup(jid, { + _setRegisteredGroupForTests(jid, { name: 'Paired Room', folder: 'paired-room', trigger: '@codex', @@ -440,7 +440,7 @@ describe('isDuplicateOfLastBotFinal (runtime function)', () => { setupChat(jid); // Register as paired room - setRegisteredGroup(jid, { + _setRegisteredGroupForTests(jid, { name: 'Paired Room', folder: 'paired-room', trigger: '@claude', @@ -448,7 +448,7 @@ describe('isDuplicateOfLastBotFinal (runtime function)', () => { agentType: 'claude-code', }); - setRegisteredGroup(jid, { + _setRegisteredGroupForTests(jid, { name: 'Paired Room', folder: 'paired-room', trigger: '@codex', diff --git a/src/ipc-auth.test.ts b/src/ipc-auth.test.ts index cba6575..3b39ec3 100644 --- a/src/ipc-auth.test.ts +++ b/src/ipc-auth.test.ts @@ -2,6 +2,7 @@ import { describe, it, expect, beforeEach, vi } from 'vitest'; import { ASSISTANT_NAME } from './config.js'; import { + _setRegisteredGroupForTests, _initTestDatabase, assignRoom, createTask, @@ -10,7 +11,6 @@ import { getRegisteredGroup, getStoredRoomSettings, getTaskById, - setRegisteredGroup, } from './db.js'; import { processTaskIpc, IpcDeps } from './ipc.js'; import { DEFAULT_WATCH_CI_MAX_DURATION_MS } from './task-watch-status.js'; @@ -52,9 +52,9 @@ beforeEach(() => { }; // Populate DB as well - setRegisteredGroup('main@g.us', MAIN_GROUP); - setRegisteredGroup('other@g.us', OTHER_GROUP); - setRegisteredGroup('third@g.us', THIRD_GROUP); + _setRegisteredGroupForTests('main@g.us', MAIN_GROUP); + _setRegisteredGroupForTests('other@g.us', OTHER_GROUP); + _setRegisteredGroupForTests('third@g.us', THIRD_GROUP); deps = { sendMessage: async () => {}, @@ -119,7 +119,7 @@ describe('schedule_task authorization', () => { ...OTHER_GROUP, agentType: 'codex', }; - setRegisteredGroup('other@g.us', groups['other@g.us']); + _setRegisteredGroupForTests('other@g.us', groups['other@g.us']); await processTaskIpc( { diff --git a/src/service-routing.test.ts b/src/service-routing.test.ts index 0e6e766..63f3c1e 100644 --- a/src/service-routing.test.ts +++ b/src/service-routing.test.ts @@ -1,10 +1,10 @@ import { beforeEach, describe, expect, it } from 'vitest'; import { + _setRegisteredGroupForTests, _setStoredRoomOwnerAgentTypeForTests, _initTestDatabase, setExplicitRoomMode, - setRegisteredGroup, } from './db.js'; import { activateCodexFailover, @@ -22,14 +22,14 @@ beforeEach(() => { describe('service-routing global failover', () => { it('uses codex-review as owner during global failover', () => { - setRegisteredGroup('dc:paired', { + _setRegisteredGroupForTests('dc:paired', { name: 'Paired Room', folder: 'paired-room', trigger: '@Andy', added_at: '2024-01-01T00:00:00.000Z', agentType: 'claude-code', }); - setRegisteredGroup('dc:paired', { + _setRegisteredGroupForTests('dc:paired', { name: 'Paired Room', folder: 'paired-room', trigger: '@Codex', @@ -57,14 +57,14 @@ describe('service-routing global failover', () => { }); it('restores default lease after global failover is cleared', () => { - setRegisteredGroup('dc:paired', { + _setRegisteredGroupForTests('dc:paired', { name: 'Paired Room', folder: 'paired-room', trigger: '@Andy', added_at: '2024-01-01T00:00:00.000Z', agentType: 'claude-code', }); - setRegisteredGroup('dc:paired', { + _setRegisteredGroupForTests('dc:paired', { name: 'Paired Room', folder: 'paired-room', trigger: '@Codex', @@ -85,14 +85,14 @@ describe('service-routing global failover', () => { }); it('uses explicit single room mode to suppress reviewer lease on dual registration', () => { - setRegisteredGroup('dc:explicit-single', { + _setRegisteredGroupForTests('dc:explicit-single', { name: 'Explicit Single', folder: 'explicit-single', trigger: '@Andy', added_at: '2024-01-01T00:00:00.000Z', agentType: 'claude-code', }); - setRegisteredGroup('dc:explicit-single', { + _setRegisteredGroupForTests('dc:explicit-single', { name: 'Explicit Single', folder: 'explicit-single', trigger: '@Codex', @@ -110,14 +110,14 @@ describe('service-routing global failover', () => { }); it('uses stored owner agent type when room_settings selects a different owner', () => { - setRegisteredGroup('dc:stored-owner-claude', { + _setRegisteredGroupForTests('dc:stored-owner-claude', { name: 'Stored Owner Claude', folder: 'stored-owner-claude', trigger: '@Andy', added_at: '2024-01-01T00:00:00.000Z', agentType: 'claude-code', }); - setRegisteredGroup('dc:stored-owner-claude', { + _setRegisteredGroupForTests('dc:stored-owner-claude', { name: 'Stored Owner Claude', folder: 'stored-owner-claude', trigger: '@Codex', @@ -139,7 +139,7 @@ describe('service-routing global failover', () => { }); it('falls back to the available service when stored owner agent type is unavailable', () => { - setRegisteredGroup('dc:stored-owner-fallback', { + _setRegisteredGroupForTests('dc:stored-owner-fallback', { name: 'Stored Owner Fallback', folder: 'stored-owner-fallback', trigger: '@Andy', @@ -157,7 +157,7 @@ describe('service-routing global failover', () => { }); it('creates a same-service reviewer lease when explicit tribunal is runnable on a solo registration', () => { - setRegisteredGroup('dc:explicit-tribunal', { + _setRegisteredGroupForTests('dc:explicit-tribunal', { name: 'Explicit Tribunal Claude', folder: 'explicit-tribunal-claude', trigger: '@Andy', @@ -175,7 +175,7 @@ describe('service-routing global failover', () => { }); it('keeps reviewer lease disabled when explicit tribunal cannot deliver the configured reviewer', () => { - setRegisteredGroup('dc:explicit-tribunal-codex', { + _setRegisteredGroupForTests('dc:explicit-tribunal-codex', { name: 'Explicit Tribunal Codex', folder: 'explicit-tribunal-codex', trigger: '@Codex',