import { afterEach, beforeEach, describe, expect, it } from 'vitest'; import { mkdtempSync, rmSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; import { init } from '../src/cli/commands/init.js'; import { loadConfig, saveConfig } from '../src/core/config.js'; import { agentIdentity, resolveAgentName } from '../src/core/services/identityService.js'; describe('agent identity resolution', () => { let cwd: string; beforeEach(() => { cwd = mkdtempSync(join(tmpdir(), 'ah-identity-')); init(cwd, { projectName: 'identity-test', yes: true }); const config = loadConfig(cwd); config.agents = { claude: { role: 'architect', aliases: ['windows-claude'] }, kimi: { role: 'implementer', aliases: ['kimi-ah'] }, }; config.roles.architect.preferredAgent = 'claude'; config.roles.implementer.preferredAgent = 'kimi'; saveConfig(cwd, config); }); afterEach(() => rmSync(cwd, { recursive: true, force: true })); it('maps aliases and roles to the canonical roster agent', () => { expect(resolveAgentName(cwd, 'kimi-ah')).toBe('kimi'); expect(resolveAgentName(cwd, 'implementer')).toBe('kimi'); expect(resolveAgentName(cwd, 'architect')).toBe('claude'); expect(agentIdentity(cwd, 'kimi').names).toEqual(new Set(['kimi', 'kimi-ah', 'implementer'])); }); it('rejects an unknown recipient when a roster is configured', () => { expect(() => resolveAgentName(cwd, 'ghost-agent')).toThrow(/unknown agent, alias, or role/i); }); });