Skip to content

Commit 27be980

Browse files
committed
fix(mcp-server): update stale delegates_to frontend-developer in test mocks
Closes #1397 PR #1396 removed legacy PLAN contract drift from rules and agent definitions, but test mock data still referenced delegates_to: 'frontend-developer' for PLAN and ACT modes. Updated all 20 occurrences across 3 spec files to match the current runtime contract: - PLAN delegates_to: 'solution-architect' (default PLAN primary agent) - ACT delegates_to: 'software-engineer' (DEFAULT_ACT_AGENT) - EVAL delegates_to: 'code-reviewer' (unchanged, already correct) Files modified: - keyword.service.spec.ts: 15 occurrences (mock config + assertions) - mcp.service.spec.ts: 3 occurrences (mock responses + assertion) - tui-interceptor.spec.ts: 2 occurrences (mock parse_mode responses) Also added mock agent data entries for solution-architect and software-engineer to support delegate_agent_info assertions, and updated resolver-based ACT tests to use backend-developer to clearly distinguish resolver override from config default.
1 parent 19ecc74 commit 27be980

3 files changed

Lines changed: 73 additions & 59 deletions

File tree

apps/mcp-server/src/keyword/keyword.service.spec.ts

Lines changed: 55 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,15 @@ const mockConfig: KeywordModesConfig = {
2121
instructions: 'Design first approach.',
2222
rules: ['rules/core.md'],
2323
agent: 'plan-mode',
24-
delegates_to: 'frontend-developer',
24+
delegates_to: 'solution-architect',
2525
defaultSpecialists: ['architecture-specialist', 'test-strategy-specialist'],
2626
},
2727
ACT: {
2828
description: 'Actual task execution phase',
2929
instructions: 'Red-Green-Refactor cycle.',
3030
rules: ['rules/core.md', 'rules/project.md'],
3131
agent: 'act-mode',
32-
delegates_to: 'frontend-developer',
32+
delegates_to: 'software-engineer',
3333
defaultSpecialists: ['code-quality-specialist', 'test-strategy-specialist'],
3434
},
3535
EVAL: {
@@ -65,6 +65,20 @@ const mockRulesContent: Record<string, string> = {
6565
};
6666

6767
const mockAgentData: Record<string, unknown> = {
68+
'solution-architect': {
69+
name: 'Solution Architect',
70+
description: 'High-level system design and architecture planning specialist',
71+
role: {
72+
expertise: ['Architecture', 'System Design', 'Patterns', 'Scalability'],
73+
},
74+
},
75+
'software-engineer': {
76+
name: 'Software Engineer',
77+
description: 'General-purpose implementation engineer with TDD focus',
78+
role: {
79+
expertise: ['TypeScript', 'TDD', 'Clean Architecture', 'Implementation'],
80+
},
81+
},
6882
'frontend-developer': {
6983
name: 'Frontend Developer',
7084
description: 'React/Next.js specialist with TDD and design system experience',
@@ -115,11 +129,11 @@ describe('KeywordService', () => {
115129
expect(result.rules[0].name).toBe('rules/core.md');
116130
expect(result.warnings).toBeUndefined();
117131
expect(result.agent).toBe('plan-mode');
118-
expect(result.delegates_to).toBe('frontend-developer');
132+
expect(result.delegates_to).toBe('solution-architect');
119133
expect(result.delegate_agent_info).toEqual({
120-
name: 'Frontend Developer',
121-
description: 'React/Next.js specialist with TDD and design system experience',
122-
expertise: ['React', 'Next.js', 'TDD', 'TypeScript'],
134+
name: 'Solution Architect',
135+
description: 'High-level system design and architecture planning specialist',
136+
expertise: ['Architecture', 'System Design', 'Patterns', 'Scalability'],
123137
});
124138
});
125139

@@ -131,11 +145,11 @@ describe('KeywordService', () => {
131145
expect(result.instructions).toContain('Red-Green-Refactor cycle.');
132146
expect(result.rules).toHaveLength(2);
133147
expect(result.agent).toBe('act-mode');
134-
expect(result.delegates_to).toBe('frontend-developer');
148+
expect(result.delegates_to).toBe('software-engineer');
135149
expect(result.delegate_agent_info).toEqual({
136-
name: 'Frontend Developer',
137-
description: 'React/Next.js specialist with TDD and design system experience',
138-
expertise: ['React', 'Next.js', 'TDD', 'TypeScript'],
150+
name: 'Software Engineer',
151+
description: 'General-purpose implementation engineer with TDD focus',
152+
expertise: ['TypeScript', 'TDD', 'Clean Architecture', 'Implementation'],
139153
});
140154
});
141155

@@ -716,13 +730,13 @@ describe('KeywordService', () => {
716730
it('includes delegate information when delegates_to is configured', async () => {
717731
const result = await service.parseMode('ACT implement feature');
718732

719-
expect(result.delegates_to).toBe('frontend-developer');
733+
expect(result.delegates_to).toBe('software-engineer');
720734
expect(result.delegate_agent_info).toEqual({
721-
name: 'Frontend Developer',
722-
description: 'React/Next.js specialist with TDD and design system experience',
723-
expertise: ['React', 'Next.js', 'TDD', 'TypeScript'],
735+
name: 'Software Engineer',
736+
description: 'General-purpose implementation engineer with TDD focus',
737+
expertise: ['TypeScript', 'TDD', 'Clean Architecture', 'Implementation'],
724738
});
725-
expect(mockLoadAgentInfo).toHaveBeenCalledWith('frontend-developer');
739+
expect(mockLoadAgentInfo).toHaveBeenCalledWith('software-engineer');
726740
});
727741

728742
it('includes different delegate for EVAL mode', async () => {
@@ -743,7 +757,7 @@ describe('KeywordService', () => {
743757

744758
const result = await service.parseMode('PLAN design feature');
745759

746-
expect(result.delegates_to).toBe('frontend-developer');
760+
expect(result.delegates_to).toBe('solution-architect');
747761
expect(result.delegate_agent_info).toBeUndefined();
748762
});
749763

@@ -752,7 +766,7 @@ describe('KeywordService', () => {
752766

753767
const result = await service.parseMode('PLAN design feature');
754768

755-
expect(result.delegates_to).toBe('frontend-developer');
769+
expect(result.delegates_to).toBe('solution-architect');
756770
expect(result.delegate_agent_info).toBeUndefined();
757771
});
758772

@@ -781,7 +795,7 @@ describe('KeywordService', () => {
781795
const result = await service.parseMode('PLAN design feature');
782796

783797
expect(result.delegate_agent_info).toEqual({
784-
name: 'frontend-developer',
798+
name: 'solution-architect',
785799
description: 'Test description',
786800
expertise: ['test'],
787801
});
@@ -806,8 +820,8 @@ describe('KeywordService', () => {
806820
expect(result.mode).toBe('PLAN');
807821
expect(result.originalPrompt).toBe('인증 기능 설계');
808822
expect(result.agent).toBe('plan-mode');
809-
expect(result.delegates_to).toBe('frontend-developer');
810-
expect(result.delegate_agent_info?.name).toBe('Frontend Developer');
823+
expect(result.delegates_to).toBe('solution-architect');
824+
expect(result.delegate_agent_info?.name).toBe('Solution Architect');
811825
});
812826

813827
it('works with default mode and includes agent information', async () => {
@@ -817,7 +831,7 @@ describe('KeywordService', () => {
817831
expect(result.originalPrompt).toBe('design auth feature');
818832
expect(result.warnings).toContain('No keyword found, defaulting to PLAN');
819833
expect(result.agent).toBe('plan-mode');
820-
expect(result.delegates_to).toBe('frontend-developer');
834+
expect(result.delegates_to).toBe('solution-architect');
821835
});
822836
});
823837
});
@@ -1128,7 +1142,7 @@ describe('KeywordService', () => {
11281142
expect(result.activation_message?.activations).toHaveLength(1);
11291143
expect(result.activation_message?.activations[0]).toMatchObject({
11301144
type: 'agent',
1131-
name: 'frontend-developer',
1145+
name: 'solution-architect',
11321146
tier: 'primary',
11331147
});
11341148
});
@@ -1139,7 +1153,7 @@ describe('KeywordService', () => {
11391153
expect(result.activation_message).toBeDefined();
11401154
expect(result.activation_message?.activations[0]).toMatchObject({
11411155
type: 'agent',
1142-
name: 'frontend-developer',
1156+
name: 'software-engineer',
11431157
tier: 'primary',
11441158
});
11451159
});
@@ -1173,7 +1187,7 @@ describe('KeywordService', () => {
11731187
const result = await service.parseMode('계획 인증 기능 설계');
11741188

11751189
expect(result.activation_message).toBeDefined();
1176-
expect(result.activation_message?.activations[0].name).toBe('frontend-developer');
1190+
expect(result.activation_message?.activations[0].name).toBe('solution-architect');
11771191
});
11781192

11791193
it('includes activation_message even without keyword (default mode)', async () => {
@@ -1323,10 +1337,10 @@ describe('KeywordService', () => {
13231337
it('falls back to default resolution if no recommendedActAgent provided', async () => {
13241338
const mockResolver = {
13251339
resolve: vi.fn().mockResolvedValue({
1326-
agentName: 'frontend-developer',
1340+
agentName: 'backend-developer',
13271341
source: 'default',
13281342
confidence: 1.0,
1329-
reason: 'ACT mode default: frontend-developer',
1343+
reason: 'ACT mode default: backend-developer',
13301344
}),
13311345
};
13321346
const serviceWithResolver = new KeywordService(
@@ -1340,7 +1354,7 @@ describe('KeywordService', () => {
13401354

13411355
const result = await serviceWithResolver.parseMode('ACT implement feature');
13421356

1343-
expect(result.delegates_to).toBe('frontend-developer');
1357+
expect(result.delegates_to).toBe('backend-developer');
13441358
const call = mockResolver.resolve.mock.calls[0];
13451359
expect(call[0]).toBe('ACT');
13461360
expect(call[1]).toBe('implement feature');
@@ -1351,10 +1365,10 @@ describe('KeywordService', () => {
13511365
it('treats empty string recommendedActAgent as undefined', async () => {
13521366
const mockResolver = {
13531367
resolve: vi.fn().mockResolvedValue({
1354-
agentName: 'frontend-developer',
1368+
agentName: 'backend-developer',
13551369
source: 'default',
13561370
confidence: 1.0,
1357-
reason: 'ACT mode default: frontend-developer',
1371+
reason: 'ACT mode default: backend-developer',
13581372
}),
13591373
};
13601374
const serviceWithResolver = new KeywordService(
@@ -1371,7 +1385,7 @@ describe('KeywordService', () => {
13711385
recommendedActAgent: '',
13721386
});
13731387

1374-
expect(result.delegates_to).toBe('frontend-developer');
1388+
expect(result.delegates_to).toBe('backend-developer');
13751389
// Should be called with undefined, not empty string
13761390
const call = mockResolver.resolve.mock.calls[0];
13771391
expect(call[0]).toBe('ACT');
@@ -1383,10 +1397,10 @@ describe('KeywordService', () => {
13831397
it('treats whitespace-only recommendedActAgent as undefined', async () => {
13841398
const mockResolver = {
13851399
resolve: vi.fn().mockResolvedValue({
1386-
agentName: 'frontend-developer',
1400+
agentName: 'backend-developer',
13871401
source: 'default',
13881402
confidence: 1.0,
1389-
reason: 'ACT mode default: frontend-developer',
1403+
reason: 'ACT mode default: backend-developer',
13901404
}),
13911405
};
13921406
const serviceWithResolver = new KeywordService(
@@ -1404,7 +1418,7 @@ describe('KeywordService', () => {
14041418
recommendedActAgent: ' ',
14051419
});
14061420

1407-
expect(result.delegates_to).toBe('frontend-developer');
1421+
expect(result.delegates_to).toBe('backend-developer');
14081422
});
14091423
});
14101424

@@ -2327,9 +2341,9 @@ describe('KeywordService', () => {
23272341
const mockLoadAgentSystemPrompt = vi.fn(
23282342
async (agentName: string, mode: Mode): Promise<AgentSystemPromptInfo | null> => ({
23292343
agentName,
2330-
displayName: 'Frontend Developer',
2344+
displayName: 'Solution Architect',
23312345
systemPrompt: `You are a ${agentName} in ${mode} mode. Follow TDD.`,
2332-
description: 'Frontend development specialist',
2346+
description: 'Architecture planning specialist',
23332347
}),
23342348
);
23352349

@@ -2344,9 +2358,9 @@ describe('KeywordService', () => {
23442358

23452359
expect(result.included_agent).toBeDefined();
23462360
expect(result.included_agent).toMatchObject({
2347-
name: 'Frontend Developer',
2348-
systemPrompt: expect.stringContaining('frontend-developer'),
2349-
expertise: ['React', 'Next.js', 'TDD', 'TypeScript'],
2361+
name: 'Solution Architect',
2362+
systemPrompt: expect.stringContaining('solution-architect'),
2363+
expertise: ['Architecture', 'System Design', 'Patterns', 'Scalability'],
23502364
});
23512365
});
23522366

@@ -2411,7 +2425,7 @@ describe('KeywordService', () => {
24112425

24122426
// Should not throw, just skip agent inclusion
24132427
expect(result.mode).toBe('PLAN');
2414-
expect(result.delegates_to).toBe('frontend-developer');
2428+
expect(result.delegates_to).toBe('solution-architect');
24152429
expect(result.included_agent).toBeUndefined();
24162430
});
24172431

@@ -2509,7 +2523,7 @@ describe('KeywordService', () => {
25092523
const result = await serviceWithNullAgent.parseMode('PLAN test');
25102524

25112525
// delegates_to should still be set from config, but delegate_agent_info should be undefined
2512-
expect(result.delegates_to).toBe('frontend-developer');
2526+
expect(result.delegates_to).toBe('solution-architect');
25132527
expect(result.delegate_agent_info).toBeUndefined();
25142528
});
25152529

@@ -2523,7 +2537,7 @@ describe('KeywordService', () => {
25232537

25242538
const result = await serviceWithStringAgent.parseMode('PLAN test');
25252539

2526-
expect(result.delegates_to).toBe('frontend-developer');
2540+
expect(result.delegates_to).toBe('solution-architect');
25272541
expect(result.delegate_agent_info).toBeUndefined();
25282542
});
25292543
});

apps/mcp-server/src/mcp/mcp.service.spec.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -129,11 +129,11 @@ const createMockKeywordService = (): Partial<KeywordService> => ({
129129
instructions: 'Red-Green-Refactor cycle',
130130
rules: [{ name: 'rules/core.md', content: 'Some rules' }],
131131
agent: 'act-mode',
132-
delegates_to: 'frontend-developer',
132+
delegates_to: 'software-engineer',
133133
delegate_agent_info: {
134-
name: 'Frontend Developer',
135-
description: 'React/Next.js frontend specialist',
136-
expertise: ['React', 'TypeScript'],
134+
name: 'Software Engineer',
135+
description: 'General-purpose implementation engineer',
136+
expertise: ['TypeScript', 'TDD'],
137137
},
138138
};
139139
} else if (firstWord === 'EVAL') {
@@ -157,11 +157,11 @@ const createMockKeywordService = (): Partial<KeywordService> => ({
157157
instructions: 'Plan the implementation',
158158
rules: [{ name: 'rules/core.md', content: 'Some rules' }],
159159
agent: 'plan-mode',
160-
delegates_to: 'frontend-developer',
160+
delegates_to: 'solution-architect',
161161
delegate_agent_info: {
162-
name: 'Frontend Developer',
163-
description: 'React/Next.js frontend specialist',
164-
expertise: ['React', 'TypeScript'],
162+
name: 'Solution Architect',
163+
description: 'Architecture planning specialist',
164+
expertise: ['Architecture', 'System Design'],
165165
},
166166
};
167167
}
@@ -914,11 +914,11 @@ describe('McpService', () => {
914914
const parsedContent = JSON.parse(result.content[0].text);
915915
expect(parsedContent.mode).toBe('ACT');
916916
expect(parsedContent.agent).toBe('act-mode');
917-
expect(parsedContent.delegates_to).toBe('frontend-developer');
917+
expect(parsedContent.delegates_to).toBe('software-engineer');
918918
expect(parsedContent.delegate_agent_info).toEqual({
919-
name: 'Frontend Developer',
920-
description: 'React/Next.js frontend specialist',
921-
expertise: ['React', 'TypeScript'],
919+
name: 'Software Engineer',
920+
description: 'General-purpose implementation engineer',
921+
expertise: ['TypeScript', 'TDD'],
922922
});
923923
});
924924

apps/mcp-server/src/tui/events/tui-interceptor.spec.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -265,14 +265,14 @@ describe('TuiInterceptor', () => {
265265
}));
266266
await new Promise(resolve => setImmediate(resolve));
267267

268-
// Second call: ACT with frontend-developer
268+
// Second call: ACT with software-engineer
269269
await interceptor.intercept('parse_mode', { prompt: 'ACT implement feature' }, async () => ({
270270
content: [
271271
{
272272
type: 'text',
273273
text: JSON.stringify({
274274
mode: 'ACT',
275-
delegates_to: 'frontend-developer',
275+
delegates_to: 'software-engineer',
276276
}),
277277
},
278278
],
@@ -286,11 +286,11 @@ describe('TuiInterceptor', () => {
286286
reason: 'replaced',
287287
}),
288288
);
289-
// frontend-developer should be activated
289+
// software-engineer should be activated
290290
expect(activatedHandler).toHaveBeenCalledWith(
291291
expect.objectContaining({
292-
agentId: 'primary:frontend-developer',
293-
name: 'frontend-developer',
292+
agentId: 'primary:software-engineer',
293+
name: 'software-engineer',
294294
isPrimary: true,
295295
}),
296296
);
@@ -618,7 +618,7 @@ describe('TuiInterceptor', () => {
618618
content: [
619619
{
620620
type: 'text',
621-
text: JSON.stringify({ mode: 'ACT', delegates_to: 'frontend-developer' }),
621+
text: JSON.stringify({ mode: 'ACT', delegates_to: 'software-engineer' }),
622622
},
623623
],
624624
}));

0 commit comments

Comments
 (0)