diff --git a/apps/mcp-server/src/agent/agent-prompt.builder.spec.ts b/apps/mcp-server/src/agent/agent-prompt.builder.spec.ts index 1544df8e..36de237a 100644 --- a/apps/mcp-server/src/agent/agent-prompt.builder.spec.ts +++ b/apps/mcp-server/src/agent/agent-prompt.builder.spec.ts @@ -119,7 +119,30 @@ describe('agent-prompt.builder', () => { expect(result).toMatch(/output|format|json|structured/i); }); - it('should include mandatory_checklist when present', () => { + it('should include mandatory_checklist from activation object format', () => { + const profileWithActivation: AgentProfile = { + ...mockAgentProfile, + activation: { + mandatory_checklist: { + '🔴 language': { + rule: 'MUST respond in Korean', + verification_key: 'language', + }, + '🔴 tdd': { + rule: 'Follow TDD cycle', + verification_key: 'tdd_cycle', + }, + }, + }, + }; + const result = buildAgentSystemPrompt(profileWithActivation, mockContext); + + expect(result).toContain('## Mandatory Checklist'); + expect(result).toContain('- [ ] MUST respond in Korean'); + expect(result).toContain('- [ ] Follow TDD cycle'); + }); + + it('should fall back to top-level array mandatory_checklist (backward compat)', () => { const profileWithChecklist: AgentProfile = { ...mockAgentProfile, mandatory_checklist: [ @@ -136,6 +159,22 @@ describe('agent-prompt.builder', () => { expect(result).toContain('- [ ] SOLID principles applied'); }); + it('should prefer activation.mandatory_checklist over top-level array', () => { + const profileWithBoth: AgentProfile = { + ...mockAgentProfile, + mandatory_checklist: ['Top-level item'], + activation: { + mandatory_checklist: { + '🔴 check': { rule: 'Activation item', verification_key: 'check' }, + }, + }, + }; + const result = buildAgentSystemPrompt(profileWithBoth, mockContext); + + expect(result).toContain('- [ ] Activation item'); + expect(result).not.toContain('Top-level item'); + }); + it('should include communication language when present', () => { const profileWithLang: AgentProfile = { ...mockAgentProfile, @@ -193,18 +232,75 @@ describe('agent-prompt.builder', () => { expect(result).toContain('**web_search**: Validate recommendations (when: Evaluating)'); }); - it('should include verification_guide when present', () => { + it('should include verification_guide from activation', () => { + const profileWithActivation: AgentProfile = { + ...mockAgentProfile, + activation: { + verification_guide: { + tdd_cycle: 'Check test file exists before implementation', + server_components: 'Verify no use client directive', + }, + }, + }; + const result = buildAgentSystemPrompt(profileWithActivation, mockContext); + + expect(result).toContain('## Verification Guide'); + expect(result).toContain('**tdd_cycle**: Check test file exists before implementation'); + expect(result).toContain('**server_components**: Verify no use client directive'); + }); + + it('should fall back to top-level verification_guide (backward compat)', () => { const profileWithVerification: AgentProfile = { ...mockAgentProfile, verification_guide: { - steps: ['Check type safety', 'Run tests', 'Review coverage'], + steps: 'Check type safety and run tests', }, }; const result = buildAgentSystemPrompt(profileWithVerification, mockContext); expect(result).toContain('## Verification Guide'); - expect(result).toContain('Check type safety'); - expect(result).toContain('Run tests'); + expect(result).toContain('**steps**: Check type safety and run tests'); + }); + + it('should include execution_order from activation (object format)', () => { + const profileWithActivation: AgentProfile = { + ...mockAgentProfile, + activation: { + execution_order: { + plan_mode: ['1. Analyze requirements', '2. Create plan'], + act_mode: ['1. Implement changes', '2. Run tests'], + }, + }, + }; + const result = buildAgentSystemPrompt(profileWithActivation, mockContext); + + expect(result).toContain('## Execution Order'); + expect(result).toContain('### plan_mode'); + expect(result).toContain('1. Analyze requirements'); + expect(result).toContain('### act_mode'); + expect(result).toContain('1. Implement changes'); + }); + + it('should include execution_order from activation (array format)', () => { + const profileWithActivation: AgentProfile = { + ...mockAgentProfile, + activation: { + execution_order: ['Step 1', 'Step 2', 'Step 3'], + }, + }; + const result = buildAgentSystemPrompt(profileWithActivation, mockContext); + + expect(result).toContain('## Execution Order'); + expect(result).toContain('1. Step 1'); + expect(result).toContain('1. Step 2'); + }); + + it('should handle agent without activation field gracefully', () => { + const result = buildAgentSystemPrompt(mockAgentProfile, mockContext); + + expect(result).not.toContain('## Mandatory Checklist'); + expect(result).not.toContain('## Verification Guide'); + expect(result).not.toContain('## Execution Order'); }); it('should handle agent without optional rich metadata gracefully', () => { diff --git a/apps/mcp-server/src/agent/agent-prompt.builder.ts b/apps/mcp-server/src/agent/agent-prompt.builder.ts index 6ca476e4..d222a8f8 100644 --- a/apps/mcp-server/src/agent/agent-prompt.builder.ts +++ b/apps/mcp-server/src/agent/agent-prompt.builder.ts @@ -76,9 +76,27 @@ export function buildAgentSystemPrompt(agentProfile: AgentProfile, context: Agen // Rich metadata from passthrough fields const rawProfile = agentProfile as Record; - - // Mandatory Checklist - if (Array.isArray(rawProfile.mandatory_checklist) && rawProfile.mandatory_checklist.length) { + const activation = rawProfile.activation as Record | undefined; + + // Mandatory Checklist — prefer activation.mandatory_checklist (object with {rule:...} items) + const activationChecklist = activation?.mandatory_checklist; + if ( + activationChecklist && + typeof activationChecklist === 'object' && + !Array.isArray(activationChecklist) + ) { + sections.push('## Mandatory Checklist'); + for (const [, item] of Object.entries(activationChecklist as Record)) { + if (item && typeof item === 'object' && 'rule' in item) { + sections.push(`- [ ] ${(item as { rule: string }).rule}`); + } + } + sections.push(''); + } else if ( + Array.isArray(rawProfile.mandatory_checklist) && + rawProfile.mandatory_checklist.length + ) { + // Backward compat: top-level array format sections.push('## Mandatory Checklist'); for (const item of rawProfile.mandatory_checklist) { sections.push(`- [ ] ${item}`); @@ -133,10 +151,34 @@ export function buildAgentSystemPrompt(agentProfile: AgentProfile, context: Agen sections.push(''); } - // Verification Guide - if (rawProfile.verification_guide) { + // Verification Guide — prefer activation.verification_guide + const verificationGuide = activation?.verification_guide ?? rawProfile.verification_guide; + if (verificationGuide && typeof verificationGuide === 'object') { sections.push('## Verification Guide'); - sections.push(JSON.stringify(rawProfile.verification_guide, null, 2)); + for (const [key, desc] of Object.entries(verificationGuide as Record)) { + sections.push(`- **${key}**: ${desc}`); + } + sections.push(''); + } + + // Execution Order — from activation.execution_order + const executionOrder = activation?.execution_order; + if (executionOrder && typeof executionOrder === 'object' && !Array.isArray(executionOrder)) { + sections.push('## Execution Order'); + for (const [phase, steps] of Object.entries(executionOrder as Record)) { + if (Array.isArray(steps) && steps.length) { + sections.push(`### ${phase}`); + for (const step of steps) { + sections.push(`${step}`); + } + } + } + sections.push(''); + } else if (Array.isArray(executionOrder) && executionOrder.length) { + sections.push('## Execution Order'); + for (const step of executionOrder) { + sections.push(`1. ${step}`); + } sections.push(''); }