diff --git a/.claude/rules/custom-instructions.md b/.claude/rules/custom-instructions.md
index f64899d0..d6b18ae1 100644
--- a/.claude/rules/custom-instructions.md
+++ b/.claude/rules/custom-instructions.md
@@ -123,125 +123,50 @@ Even if plan separates TDD into individual steps (e.g., Step 1: Write test, Step
-**When user message starts with PLAN, ACT, EVAL, or AUTO keyword (or localized: Korean 계획/실행/평가/자동, Japanese 計画/実行/評価/自動, Chinese 计划/执行/评估/自动, Spanish PLANIFICAR/ACTUAR/EVALUAR/AUTOMÁTICO):**
+**When user message starts with PLAN, ACT, EVAL, or AUTO keyword (or localized equivalents):**
-1. **IMMEDIATELY** call `parse_mode` MCP tool with the user's prompt
-2. Follow the returned `instructions` **EXACTLY**
-3. Apply the returned `rules` as context
-4. If `warnings` are present, inform the user
-
-**This is MANDATORY, not optional.**
-
-Failure to call `parse_mode` when these keywords are present will result in:
-- Missed critical checklists (Devil's Advocate Analysis, Impact Radius Analysis)
-- Incomplete evaluations
-- Quality issues not caught before deployment
-
-**Red Flags** (STOP if you think these):
-| Thought | Reality |
-|---------|---------|
-| "I can handle EVAL myself" | NO. Call parse_mode FIRST. |
-| "The rules are similar anyway" | NO. Each mode has specific checklists. |
-| "I'll save a tool call" | NO. parse_mode MUST be called FIRST. |
-| "I already know what to do" | NO. Rules may have been updated. |
+1. Call `activate` MCP tool with the user's prompt (preferred in Claude Code)
+2. **Fallback**: Call `parse_mode` if `activate` is unavailable
+3. Follow the returned `rules` as context
+4. Use returned `specialists` to run a council via Claude native Teams
-Examples:
-- `PLAN design auth feature` → **immediately** call parse_mode → work in PLAN mode
-- `AUTO implement user dashboard` → **immediately** call parse_mode → autonomous PLAN→ACT→EVAL cycle
-
-## 🔴 MANDATORY: Parallel Specialist Agent Execution
-
-
-
-**When `parse_mode` returns `dispatchReady`, use it directly with the Task tool — no extra calls needed.**
-
-**Outer Transport Selection (before dispatch):**
-- [ ] Check `availableStrategies` in `parse_mode` response (outer transport options)
-- [ ] If `["subagent", "taskmaestro"]` → AskUserQuestion to choose outer strategy
-- [ ] If `taskmaestroInstallHint` present and user wants taskmaestro → guide installation
-- [ ] Pass chosen strategy to `dispatch_agents(executionStrategy: ...)`
-- [ ] Teams (inner coordination, experimental) may be used within a session if APIs are available
-
-**Quick Checklist (Auto-Dispatch - Preferred):**
-- [ ] Check `dispatchReady` in `parse_mode` response
-- [ ] Use `dispatchReady.primaryAgent.dispatchParams` with Task tool
-- [ ] Use `dispatchReady.parallelAgents[].dispatchParams` with Task tool (`run_in_background: true`)
-- [ ] Collect results with `TaskOutput`
-- [ ] Summarize all findings
-
-**Fallback (if `dispatchReady` is not present):**
-- [ ] Call `dispatch_agents` or `prepare_parallel_agents` with recommended specialists
-- [ ] Execute each agent via Task tool (`subagent_type: "general-purpose"`, `run_in_background: true`)
-- [ ] Display activation status
-- [ ] Collect results with `TaskOutput`
-- [ ] Summarize all findings
-
-**Mode-specific Specialists:**
-
-| Mode | Specialists |
-|------|-------------|
-| **PLAN** | 🏛️ architecture, 🧪 test-strategy, 📨 event-architecture, 🔗 integration, 📊 observability, 🔄 migration |
-| **ACT** | 📏 code-quality, 🧪 test-strategy, 📨 event-architecture, 🔗 integration |
-| **EVAL** | 🔒 security, ♿ accessibility, ⚡ performance, 📏 code-quality, 📨 event-architecture, 🔗 integration, 📊 observability, 🔄 migration |
-| **AUTO** | 🏛️ architecture, 🧪 test-strategy, 🔒 security, 📏 code-quality, 📨 event-architecture, 🔗 integration, 📊 observability, 🔄 migration |
-
-> **Note:** SubAgent and TaskMaestro are **outer transport** strategies (one per invocation, user choice).
-> Teams is an **inner coordination** layer (experimental) that can optionally run within either outer strategy.
-> See the [Execution Model](../../packages/rules/.ai-rules/adapters/claude-code.md#execution-model-outer-transport-vs-inner-coordination) for details.
-
-**📖 Full Guide:** [Parallel Specialist Agents Execution](../../packages/rules/.ai-rules/adapters/claude-code.md#parallel-specialist-agents-execution)
-
-
-
-## 🔴 MANDATORY: Auto-Dispatch Enforcement
-
-
-
-**When `parse_mode` returns `dispatch="auto"`, you MUST dispatch all recommended specialists. No exceptions.**
-
-### Core Rule
-
-If the `parse_mode` response contains `dispatch="auto"` or `dispatchReady` with specialist agents:
-1. **MUST** dispatch every listed specialist — skipping any is a protocol violation
-2. Use the selected **outer transport** (SubAgent or TaskMaestro) to dispatch specialists
-3. **Optionally** use Teams as inner coordination within a session (experimental, requires runtime API availability)
-4. **Report results** via the dispatch mechanism (TaskOutput for SubAgent, SendMessage for Teams)
-
-### Red Flags (STOP if you think these)
-
-| Thought | Reality |
-|---------|---------|
-| "I can handle this analysis myself" | NO. Specialists have domain expertise you lack. Dispatch them. |
-| "It's just a small change, no need for specialists" | NO. dispatch="auto" means the system determined specialists are needed. |
-| "I'll save time by skipping dispatch" | NO. Skipping specialists causes missed issues that cost more time later. |
-| "The specialists will just repeat what I already know" | NO. Specialists catch domain-specific issues you would miss. |
-| "I'll dispatch them later after I look at the code" | NO. Dispatch IMMEDIATELY when dispatch="auto" is returned. |
+## 🔴 MANDATORY: Specialist Council Execution
-
+
-## 🔴 MANDATORY: Context Document Management
+**When `activate` returns specialists, run them as a council via Claude native Teams.**
-
+### Workflow
-**Fixed file `docs/codingbuddy/context.md` persists PLAN → ACT → EVAL context across context compaction.**
+1. Call `activate({ prompt })` → get rules, primaryAgent, specialists
+2. Create a Claude native Team with the returned specialists as teammates
+3. Each specialist independently analyzes the task
+4. Specialists cross-review each other's findings
+5. Collect consensus: approve | concern | reject
+6. Summarize all findings to user
-### How It Works
+### Fallback (non-Teams environments)
-`parse_mode` **automatically** manages the context document:
+If Teams is not available, dispatch specialists as parallel subagents:
+- Use `Agent` tool with `run_in_background: true` for each specialist
+- Collect results and synthesize
-- **PLAN/AUTO mode**: Resets (deletes and recreates) the context document
-- **ACT/EVAL mode**: Appends a new section to the existing document
+
-### Required Workflow
+## Claude Code Native Feature Mapping
-**In ALL modes:**
-1. `parse_mode` automatically reads/creates context
-2. Review `contextDocument` for previous decisions and notes
-3. Before completing: `update_context` to persist current work
+Use Claude Code native features instead of codingbuddy equivalents:
-
+| Need | Native Feature | Instead of |
+|------|----------------|------------|
+| Cross-session context | **Claude Code Memory** | `update_context` / `create_briefing` / `resume_session` |
+| Specialist debate | **Claude native Teams** | `dispatch_agents` subagent strategy |
+| Task exploration | **/dream** | `analyze_task` |
+| Planning with approval | **EnterPlanMode** | `parse_mode` planning stage |
+| Repeated execution | **/loop** | AUTO mode repetition |
+| Clarification | **AskUserQuestion** | clarification gate |
## Claude Code Specific
@@ -250,7 +175,6 @@ If the `parse_mode` response contains `dispatch="auto"` or `dispatchReady` with
- Provide clear, actionable feedback
- Reference project context from `packages/rules/.ai-rules/rules/project.md`
- Follow PLAN → ACT → EVAL workflow when appropriate
-- Use AUTO mode for autonomous quality-driven development cycles
## Full Documentation
diff --git a/.claude/rules/tool-priority.md b/.claude/rules/tool-priority.md
index 5469001e..333c7fe1 100644
--- a/.claude/rules/tool-priority.md
+++ b/.claude/rules/tool-priority.md
@@ -1,73 +1,79 @@
-# Tool Priority: codingbuddy vs oh-my-claudecode (OMC)
+# Tool Priority: Claude Code Native > codingbuddy > OMC
## Core Principle
-**codingbuddy FIRST** — Use codingbuddy tools for all workflow management, agent dispatch, and quality control.
-**OMC for unique features only** — Use OMC tools when they provide capabilities codingbuddy does not.
+1. **Claude Code native FIRST** — Memory, Teams, Plan mode, /dream, /loop handle orchestration natively
+2. **codingbuddy for unique value** — Rules, agents, checklists, quality reports are codingbuddy's core
+3. **OMC for dev tools** — LSP, AST grep, REPL, git-master when needed
---
-## codingbuddy FIRST
+## Layer 1: Claude Code Native (highest priority)
-Always reach for these codingbuddy tools before any OMC equivalent:
+These features are built into Claude Code and should be used instead of codingbuddy equivalents:
+
+| Native Feature | Purpose | Replaces |
+|----------------|---------|----------|
+| **Claude Code Memory** | Cross-session context persistence | `update_context`, `create_briefing`, `resume_session` |
+| **Claude native Teams** | Run specialist agents as teammates for real-time debate | `dispatch_agents` subagent strategy |
+| **EnterPlanMode** | Structured planning with user approval | `parse_mode` planning stage routing |
+| **/dream** | Autonomous task exploration and analysis | `analyze_task` |
+| **/loop** | Recurring execution on interval | `parse_mode` AUTO mode repetition |
+| **AskUserQuestion** | Clarification from user | `parse_mode` clarification gate |
+
+---
+
+## Layer 2: codingbuddy (unique value)
+
+Use codingbuddy tools for capabilities Claude Code does not provide natively:
| Tool | Purpose |
|------|---------|
-| `parse_mode` | Mode management (PLAN/ACT/EVAL/AUTO), agent activation, context init |
-| `dispatch_agents` | Agent dispatch with Task tool-ready params |
-| `analyze_task` | Pre-planning task analysis, risk assessment, specialist recommendations |
-| `update_context` | Context persistence across PLAN → ACT → EVAL modes |
-| `generate_checklist` | Contextual checklists (security, a11y, performance, testing) |
+| `activate` | **One-shot entry point**: rules + primary agent + specialists + discussion format |
+| `parse_mode` | Legacy mode entry (for non-Claude Code hosts: Cursor, Codex, etc.) |
| `search_rules` | Query project rules and guidelines |
| `get_agent_details` | Agent profile and expertise lookup |
+| `generate_checklist` | Contextual checklists (security, a11y, performance, testing) |
| `get_project_config` | Tech stack, architecture, language settings |
-| `prepare_parallel_agents` | Ready-to-use prompts for parallel specialist agents |
| `pr_quality_report` | Run specialist agents on changed files for PR quality |
-| `create_briefing` | Capture session state for cross-session recovery |
-| `resume_session` | Load previous session briefing |
| `get_rule_impact_report` | Rule effectiveness analytics |
---
-## OMC Only
+## Layer 3: OMC (dev tools)
-Use these OMC tools when the capability is not available in codingbuddy:
+Use OMC tools for capabilities neither Claude Code nor codingbuddy provide:
| Tool / Skill | Purpose |
|--------------|---------|
| LSP tools (`lsp_hover`, `lsp_goto_definition`, `lsp_find_references`, etc.) | Language server protocol — type info, definitions, references |
| AST grep (`ast_grep_search`, `ast_grep_replace`) | Structural code search and refactoring |
| Python REPL (`python_repl`) | Interactive data analysis and computation |
-| State tools (`state_read`, `state_write`, `state_clear`) | Mode state persistence for autopilot/ralph/ultrawork |
-| Notepad tools (`notepad_read`, `notepad_write_*`) | Session notes and compaction-resilient memory |
-| Project memory (`project_memory_*`) | Long-term project knowledge persistence |
| `/git-master` | Atomic commits, rebasing, history management |
| `/build-fix` | Build and TypeScript error resolution |
| `/deepsearch` | Thorough multi-pass codebase search |
-| `/team`, `/swarm` | Multi-agent coordination with shared task lists |
-| `/ultrawork`, `/autopilot`, `/ralph` | Autonomous execution loops |
-| `/pipeline` | Sequential/branching agent workflows |
---
-## Overlap Matrix
-
-When both tools could apply, codingbuddy wins:
+## Quick Decision Matrix
| Use Case | Use This | Not This |
|----------|----------|----------|
-| Starting PLAN/ACT/EVAL mode | `parse_mode` | OMC mode state tools |
-| Dispatching specialist agents | `dispatch_agents` | OMC `/team` or `/swarm` |
-| Code/security review | codingbuddy `search_rules` + specialists | OMC `/code-review`, `/security-review` |
-| Context across sessions | `update_context` | OMC notepad/project memory |
-| Task analysis before planning | `analyze_task` | Ad-hoc OMC tools |
-| Checklists (security, a11y) | `generate_checklist` | Manual OMC review |
+| Starting a workflow | `activate` | `parse_mode` (in Claude Code) |
+| Running specialist council | Claude native Teams | subagent dispatch |
+| Cross-session context | Claude Code Memory | `update_context` / `create_briefing` |
+| Task analysis | `/dream` | `analyze_task` |
+| Repeated execution | `/loop` | AUTO mode cycle |
+| Clarification | AskUserQuestion | clarification gate |
+| Rules & checklists | codingbuddy `search_rules`, `generate_checklist` | — |
+| Code review quality | codingbuddy `pr_quality_report` | OMC `/code-review` |
+| Type info & references | OMC LSP tools | — |
---
## Decision Rationale
-- codingbuddy tools are project-aware and integrate with the PLAN/ACT/EVAL workflow
-- OMC tools are general-purpose developer tools without project context
-- Using codingbuddy first ensures consistent quality gates and audit trail via `docs/codingbuddy/context.md`
-- OMC's unique capabilities (LSP, AST, REPL) complement codingbuddy; they do not replace it
+- Claude Code native features handle orchestration (memory, teams, planning, loops) better than MCP tools
+- codingbuddy's unique value is **rules, agents, and checklists** — domain knowledge, not orchestration
+- OMC's unique value is **dev tooling** (LSP, AST, REPL) — code intelligence, not workflow
+- `parse_mode` remains available for backward compatibility with non-Claude Code hosts
diff --git a/apps/mcp-server/src/agent/teams-capability.service.spec.ts b/apps/mcp-server/src/agent/teams-capability.service.spec.ts
index 7ac392d5..856391a3 100644
--- a/apps/mcp-server/src/agent/teams-capability.service.spec.ts
+++ b/apps/mcp-server/src/agent/teams-capability.service.spec.ts
@@ -2,18 +2,28 @@ import { describe, it, expect, beforeEach, vi, afterEach } from 'vitest';
import { TeamsCapabilityService } from './teams-capability.service';
import type { ConfigService } from '../config/config.service';
-function createMockConfigService(experimental?: { teamsCoordination?: boolean }): ConfigService {
+function createMockConfigService(
+ experimental?: { teamsCoordination?: boolean },
+ clientName?: string,
+): ConfigService {
return {
getSettings: vi.fn().mockResolvedValue({ experimental }),
+ getClientName: vi.fn().mockReturnValue(clientName),
} as unknown as ConfigService;
}
describe('TeamsCapabilityService', () => {
let originalEnv: string | undefined;
+ let originalClaudeCode: string | undefined;
+ let originalClaudeEntrypoint: string | undefined;
beforeEach(() => {
originalEnv = process.env.CODINGBUDDY_TEAMS_ENABLED;
+ originalClaudeCode = process.env.CLAUDE_CODE;
+ originalClaudeEntrypoint = process.env.CLAUDE_CODE_ENTRYPOINT;
delete process.env.CODINGBUDDY_TEAMS_ENABLED;
+ delete process.env.CLAUDE_CODE;
+ delete process.env.CLAUDE_CODE_ENTRYPOINT;
});
afterEach(() => {
@@ -22,6 +32,16 @@ describe('TeamsCapabilityService', () => {
} else {
delete process.env.CODINGBUDDY_TEAMS_ENABLED;
}
+ if (originalClaudeCode !== undefined) {
+ process.env.CLAUDE_CODE = originalClaudeCode;
+ } else {
+ delete process.env.CLAUDE_CODE;
+ }
+ if (originalClaudeEntrypoint !== undefined) {
+ process.env.CLAUDE_CODE_ENTRYPOINT = originalClaudeEntrypoint;
+ } else {
+ delete process.env.CLAUDE_CODE_ENTRYPOINT;
+ }
});
describe('getStatus', () => {
@@ -125,6 +145,43 @@ describe('TeamsCapabilityService', () => {
});
});
+ describe('Claude Code auto-detection', () => {
+ it('should auto-enable when CLAUDE_CODE=1 is set', async () => {
+ process.env.CLAUDE_CODE = '1';
+ const service = new TeamsCapabilityService(createMockConfigService());
+ const status = await service.getStatus();
+
+ expect(status.available).toBe(true);
+ expect(status.source).toBe('claude-native');
+ expect(status.reason).toContain('Claude Code');
+ });
+
+ it('should auto-enable when CLAUDE_CODE_ENTRYPOINT is set', async () => {
+ process.env.CLAUDE_CODE_ENTRYPOINT = '/some/path';
+ const service = new TeamsCapabilityService(createMockConfigService());
+ const status = await service.getStatus();
+
+ expect(status.available).toBe(true);
+ expect(status.source).toBe('claude-native');
+ });
+
+ it('should auto-enable when clientName is claude-code', async () => {
+ const service = new TeamsCapabilityService(createMockConfigService(undefined, 'claude-code'));
+ const status = await service.getStatus();
+
+ expect(status.available).toBe(true);
+ expect(status.source).toBe('claude-native');
+ });
+
+ it('should not auto-enable for other clients', async () => {
+ const service = new TeamsCapabilityService(createMockConfigService(undefined, 'cursor'));
+ const status = await service.getStatus();
+
+ expect(status.available).toBe(false);
+ expect(status.source).toBe('default');
+ });
+ });
+
describe('readEnvFlag', () => {
it('should return undefined when env var is not set', () => {
const service = new TeamsCapabilityService(createMockConfigService());
@@ -166,7 +223,7 @@ describe('TeamsCapabilityService', () => {
expect(status).toHaveProperty('source');
expect(typeof status.available).toBe('boolean');
expect(typeof status.reason).toBe('string');
- expect(['config', 'environment', 'default']).toContain(status.source);
+ expect(['config', 'environment', 'claude-native', 'default']).toContain(status.source);
});
});
});
diff --git a/apps/mcp-server/src/agent/teams-capability.service.ts b/apps/mcp-server/src/agent/teams-capability.service.ts
index 56a352cd..5813d364 100644
--- a/apps/mcp-server/src/agent/teams-capability.service.ts
+++ b/apps/mcp-server/src/agent/teams-capability.service.ts
@@ -49,10 +49,21 @@ export class TeamsCapabilityService {
return status;
}
- // 3. Default: disabled
+ // 3. Auto-detect Claude Code environment (native Teams support)
+ if (this.isClaudeCodeEnvironment()) {
+ const status: TeamsCapabilityStatus = {
+ available: true,
+ reason: 'Auto-enabled: Claude Code environment detected with native Teams support',
+ source: 'claude-native',
+ };
+ this.logger.debug(`Teams capability: ${status.reason}`);
+ return status;
+ }
+
+ // 4. Default: disabled for non-Claude Code hosts
const status: TeamsCapabilityStatus = {
available: false,
- reason: 'Teams coordination is experimental and disabled by default',
+ reason: 'Teams coordination disabled by default for non-Claude Code hosts',
source: 'default',
};
this.logger.debug(`Teams capability: ${status.reason}`);
@@ -67,6 +78,18 @@ export class TeamsCapabilityService {
return status.available;
}
+ /**
+ * Detect whether running inside a Claude Code environment.
+ * Claude Code sets specific env vars that distinguish it from other hosts.
+ */
+ private isClaudeCodeEnvironment(): boolean {
+ return (
+ process.env.CLAUDE_CODE === '1' ||
+ process.env.CLAUDE_CODE_ENTRYPOINT !== undefined ||
+ this.configService.getClientName() === 'claude-code'
+ );
+ }
+
/**
* Read the CODINGBUDDY_TEAMS_ENABLED environment variable.
* Returns undefined when not set, boolean when explicitly set.
diff --git a/apps/mcp-server/src/agent/teams-capability.types.ts b/apps/mcp-server/src/agent/teams-capability.types.ts
index 64d8d14e..00898396 100644
--- a/apps/mcp-server/src/agent/teams-capability.types.ts
+++ b/apps/mcp-server/src/agent/teams-capability.types.ts
@@ -17,4 +17,5 @@ export interface TeamsCapabilityStatus {
export type TeamsCapabilitySource =
| 'config' // experimental.teamsCoordination in codingbuddy.config.json
| 'environment' // CODINGBUDDY_TEAMS_ENABLED env var
+ | 'claude-native' // Auto-detected Claude Code environment with native Teams support
| 'default'; // no explicit signal, default to disabled
diff --git a/apps/mcp-server/src/mcp/handlers/activate.handler.spec.ts b/apps/mcp-server/src/mcp/handlers/activate.handler.spec.ts
new file mode 100644
index 00000000..a8f653e0
--- /dev/null
+++ b/apps/mcp-server/src/mcp/handlers/activate.handler.spec.ts
@@ -0,0 +1,315 @@
+import { describe, it, expect, vi, beforeEach } from 'vitest';
+import { ActivateHandler } from './activate.handler';
+import type { AgentService } from '../../agent/agent.service';
+import type { TeamsCapabilityService } from '../../agent/teams-capability.service';
+import type { KeywordService } from '../../keyword/keyword.service';
+import type { RulesService } from '../../rules/rules.service';
+
+function createMockKeywordService(): KeywordService {
+ return {
+ getRulesForMode: vi.fn().mockResolvedValue([
+ { name: 'rules/core.md', content: '# Core rules' },
+ { name: 'rules/augmented-coding.md', content: '# Augmented coding' },
+ ]),
+ } as unknown as KeywordService;
+}
+
+function createMockAgentService(): AgentService {
+ return {
+ getAgentSystemPrompt: vi.fn().mockResolvedValue({
+ agentName: 'plan-mode-agent',
+ displayName: 'Plan Mode Agent',
+ systemPrompt: 'You are a planning agent...',
+ description: 'Planning specialist',
+ }),
+ prepareParallelAgents: vi.fn().mockResolvedValue({
+ agents: [
+ {
+ id: 'security-specialist',
+ displayName: 'Security Specialist',
+ taskPrompt: 'Analyze security...',
+ description: 'Security analysis',
+ },
+ {
+ id: 'architecture-specialist',
+ displayName: 'Architecture Specialist',
+ taskPrompt: 'Review architecture...',
+ description: 'Architecture review',
+ },
+ ],
+ parallelExecutionHint: 'Use Task tool...',
+ }),
+ } as unknown as AgentService;
+}
+
+function createMockRulesService(): RulesService {
+ return {
+ getRuleContent: vi.fn().mockResolvedValue(
+ JSON.stringify({
+ modes: {
+ PLAN: {
+ defaultSpecialists: ['architecture-specialist', 'test-strategy-specialist'],
+ },
+ ACT: { defaultSpecialists: ['code-quality-specialist'] },
+ EVAL: {
+ defaultSpecialists: ['security-specialist', 'performance-specialist'],
+ },
+ AUTO: { defaultSpecialists: ['architecture-specialist'] },
+ },
+ }),
+ ),
+ } as unknown as RulesService;
+}
+
+function createMockTeamsCapability(available = true): TeamsCapabilityService {
+ return {
+ getStatus: vi.fn().mockResolvedValue({
+ available,
+ reason: available ? 'Auto-enabled: Claude Code environment detected' : 'Disabled by default',
+ source: available ? 'claude-native' : 'default',
+ }),
+ } as unknown as TeamsCapabilityService;
+}
+
+describe('ActivateHandler', () => {
+ let handler: ActivateHandler;
+ let keywordService: KeywordService;
+ let agentService: AgentService;
+ let rulesService: RulesService;
+ let teamsCapability: TeamsCapabilityService;
+
+ beforeEach(() => {
+ keywordService = createMockKeywordService();
+ agentService = createMockAgentService();
+ rulesService = createMockRulesService();
+ teamsCapability = createMockTeamsCapability();
+ handler = new ActivateHandler(keywordService, agentService, rulesService, teamsCapability);
+ });
+
+ describe('getToolDefinitions', () => {
+ it('should define the activate tool', () => {
+ const definitions = handler.getToolDefinitions();
+ expect(definitions).toHaveLength(1);
+ expect(definitions[0].name).toBe('activate');
+ });
+
+ it('should require prompt parameter', () => {
+ const definitions = handler.getToolDefinitions();
+ expect(definitions[0].inputSchema.required).toEqual(['prompt']);
+ });
+
+ it('should have mode and primaryAgent as optional', () => {
+ const definitions = handler.getToolDefinitions();
+ const props = definitions[0].inputSchema.properties;
+ expect(props).toHaveProperty('prompt');
+ expect(props).toHaveProperty('mode');
+ expect(props).toHaveProperty('primaryAgent');
+ });
+ });
+
+ describe('handle', () => {
+ it('should return null for unknown tools', async () => {
+ const result = await handler.handle('unknown_tool', {});
+ expect(result).toBeNull();
+ });
+
+ it('should return error for missing prompt', async () => {
+ const result = await handler.handle('activate', {});
+ expect(result?.isError).toBe(true);
+ expect(result?.content[0].text).toContain('Missing required parameter: prompt');
+ });
+
+ it('should return complete response for valid prompt', async () => {
+ const result = await handler.handle('activate', {
+ prompt: 'PLAN design auth feature',
+ });
+
+ expect(result).not.toBeNull();
+ expect(result?.isError).toBeFalsy();
+
+ const data = JSON.parse(result!.content[0].text);
+ expect(data.mode).toBe('PLAN');
+ expect(data.rules).toBeDefined();
+ expect(data.primaryAgent).toBeDefined();
+ expect(data.specialists).toBeDefined();
+ expect(data.discussion).toBeDefined();
+ expect(data.nativeIntegration).toBeDefined();
+ });
+ });
+
+ describe('mode resolution', () => {
+ it('should auto-detect PLAN from prompt', async () => {
+ const result = await handler.handle('activate', { prompt: 'PLAN design auth' });
+ const data = JSON.parse(result!.content[0].text);
+ expect(data.mode).toBe('PLAN');
+ });
+
+ it('should auto-detect ACT from prompt', async () => {
+ const result = await handler.handle('activate', { prompt: 'ACT implement the feature' });
+ const data = JSON.parse(result!.content[0].text);
+ expect(data.mode).toBe('ACT');
+ });
+
+ it('should auto-detect EVAL from prompt', async () => {
+ const result = await handler.handle('activate', { prompt: 'EVAL review the code' });
+ const data = JSON.parse(result!.content[0].text);
+ expect(data.mode).toBe('EVAL');
+ });
+
+ it('should use explicit mode parameter over prompt keyword', async () => {
+ const result = await handler.handle('activate', {
+ prompt: 'PLAN some task',
+ mode: 'EVAL',
+ });
+ const data = JSON.parse(result!.content[0].text);
+ expect(data.mode).toBe('EVAL');
+ });
+
+ it('should default to PLAN when no keyword found', async () => {
+ const result = await handler.handle('activate', { prompt: 'design auth feature' });
+ const data = JSON.parse(result!.content[0].text);
+ expect(data.mode).toBe('PLAN');
+ });
+
+ it('should support Korean keywords', async () => {
+ const result = await handler.handle('activate', { prompt: '실행 인증 기능 구현' });
+ const data = JSON.parse(result!.content[0].text);
+ expect(data.mode).toBe('ACT');
+ });
+ });
+
+ describe('rules loading', () => {
+ it('should call getRulesForMode with detected mode', async () => {
+ await handler.handle('activate', { prompt: 'EVAL review code' });
+ expect(keywordService.getRulesForMode).toHaveBeenCalledWith('EVAL', 'standard');
+ });
+
+ it('should include rules in response', async () => {
+ const result = await handler.handle('activate', { prompt: 'PLAN task' });
+ const data = JSON.parse(result!.content[0].text);
+ expect(data.rules).toHaveLength(2);
+ expect(data.rules[0]).toHaveProperty('name');
+ expect(data.rules[0]).toHaveProperty('content');
+ });
+ });
+
+ describe('primary agent resolution', () => {
+ it('should resolve default primary agent for mode', async () => {
+ await handler.handle('activate', { prompt: 'PLAN task' });
+ expect(agentService.getAgentSystemPrompt).toHaveBeenCalledWith(
+ 'plan-mode-agent',
+ expect.objectContaining({ mode: 'PLAN' }),
+ );
+ });
+
+ it('should use explicit primaryAgent parameter', async () => {
+ await handler.handle('activate', {
+ prompt: 'PLAN task',
+ primaryAgent: 'solution-architect',
+ });
+ expect(agentService.getAgentSystemPrompt).toHaveBeenCalledWith(
+ 'solution-architect',
+ expect.objectContaining({ mode: 'PLAN' }),
+ );
+ });
+
+ it('should include primaryAgent in response', async () => {
+ const result = await handler.handle('activate', { prompt: 'PLAN task' });
+ const data = JSON.parse(result!.content[0].text);
+ expect(data.primaryAgent).toEqual({
+ name: 'plan-mode-agent',
+ displayName: 'Plan Mode Agent',
+ systemPrompt: 'You are a planning agent...',
+ });
+ });
+
+ it('should handle primary agent resolution failure gracefully', async () => {
+ (agentService.getAgentSystemPrompt as ReturnType).mockRejectedValueOnce(
+ new Error('Agent not found'),
+ );
+ const result = await handler.handle('activate', { prompt: 'PLAN task' });
+ const data = JSON.parse(result!.content[0].text);
+ expect(data.primaryAgent).toBeNull();
+ });
+ });
+
+ describe('specialist resolution', () => {
+ it('should load default specialists from keyword-modes.json', async () => {
+ await handler.handle('activate', { prompt: 'PLAN task' });
+ expect(rulesService.getRuleContent).toHaveBeenCalledWith('keyword-modes.json');
+ });
+
+ it('should merge mode defaults with context-aware patterns', async () => {
+ const result = await handler.handle('activate', {
+ prompt: 'PLAN design authentication with JWT security',
+ });
+ const data = JSON.parse(result!.content[0].text);
+ // Should include both mode defaults (architecture, test-strategy)
+ // and context-detected (security from "authentication" + "security")
+ const specialistNames = data.specialists.map((s: { name: string }) => s.name);
+ expect(specialistNames.length).toBeGreaterThan(0);
+ });
+
+ it('should prepare specialists with full verbosity', async () => {
+ await handler.handle('activate', { prompt: 'PLAN task' });
+ expect(agentService.prepareParallelAgents).toHaveBeenCalledWith(
+ 'PLAN',
+ expect.any(Array),
+ undefined,
+ expect.any(String),
+ 'full',
+ );
+ });
+
+ it('should include specialist prompts and domains in response', async () => {
+ const result = await handler.handle('activate', { prompt: 'PLAN task' });
+ const data = JSON.parse(result!.content[0].text);
+ expect(data.specialists.length).toBeGreaterThan(0);
+ for (const specialist of data.specialists) {
+ expect(specialist).toHaveProperty('name');
+ expect(specialist).toHaveProperty('displayName');
+ expect(specialist).toHaveProperty('prompt');
+ expect(specialist).toHaveProperty('domain');
+ }
+ });
+ });
+
+ describe('discussion format', () => {
+ it('should include discussion guide in response', async () => {
+ const result = await handler.handle('activate', { prompt: 'PLAN task' });
+ const data = JSON.parse(result!.content[0].text);
+ expect(data.discussion).toEqual({
+ format: 'Each specialist: approve|concern|reject + reasoning + suggestedChanges',
+ consensus: 'No rejections = consensus reached',
+ crossReview: "Specialists review each other's opinions",
+ });
+ });
+ });
+
+ describe('native integration', () => {
+ it('should indicate Teams available when enabled', async () => {
+ const result = await handler.handle('activate', { prompt: 'PLAN task' });
+ const data = JSON.parse(result!.content[0].text);
+ expect(data.nativeIntegration.teams).toContain('native Teams');
+ });
+
+ it('should indicate how to enable Teams when disabled', async () => {
+ handler = new ActivateHandler(
+ keywordService,
+ agentService,
+ rulesService,
+ createMockTeamsCapability(false),
+ );
+ const result = await handler.handle('activate', { prompt: 'PLAN task' });
+ const data = JSON.parse(result!.content[0].text);
+ expect(data.nativeIntegration.teams).toContain('CODINGBUDDY_TEAMS_ENABLED');
+ });
+
+ it('should include Memory and orchestration guidance', async () => {
+ const result = await handler.handle('activate', { prompt: 'PLAN task' });
+ const data = JSON.parse(result!.content[0].text);
+ expect(data.nativeIntegration.memory).toContain('Memory');
+ expect(data.nativeIntegration.orchestration).toContain('natively');
+ });
+ });
+});
diff --git a/apps/mcp-server/src/mcp/handlers/activate.handler.ts b/apps/mcp-server/src/mcp/handlers/activate.handler.ts
new file mode 100644
index 00000000..b4e177f6
--- /dev/null
+++ b/apps/mcp-server/src/mcp/handlers/activate.handler.ts
@@ -0,0 +1,337 @@
+import { Injectable, Inject, Logger } from '@nestjs/common';
+import type { ToolDefinition } from './base.handler';
+import type { ToolResponse } from '../response.utils';
+import { AbstractHandler } from './abstract-handler';
+import { createJsonResponse, createErrorResponse } from '../response.utils';
+import { AgentService } from '../../agent/agent.service';
+import { TeamsCapabilityService } from '../../agent/teams-capability.service';
+import type { KeywordService } from '../../keyword/keyword.service';
+import { KEYWORD_SERVICE } from '../../keyword/keyword.module';
+import { KEYWORDS, LOCALIZED_KEYWORD_MAP, type Mode } from '../../keyword/keyword.types';
+import { RulesService } from '../../rules/rules.service';
+import {
+ extractRequiredString,
+ extractOptionalString,
+ isValidMode,
+} from '../../shared/validation.constants';
+
+/** Default primary agents per mode (from keyword-modes.json agent field) */
+const MODE_DEFAULT_AGENTS: Record = {
+ PLAN: 'plan-mode-agent',
+ ACT: 'act-mode-agent',
+ EVAL: 'eval-mode-agent',
+ AUTO: 'auto-mode-agent',
+};
+
+/**
+ * Context-aware specialist detection patterns.
+ * Mirrors KeywordService.CONTEXT_SPECIALIST_PATTERNS for prompt analysis.
+ */
+const CONTEXT_SPECIALIST_PATTERNS: ReadonlyArray<{ pattern: RegExp; specialist: string }> = [
+ {
+ pattern: /보안|security|auth|인증|JWT|OAuth|XSS|CSRF|취약점|vulnerability/i,
+ specialist: 'security-specialist',
+ },
+ {
+ pattern: /접근성|accessibility|a11y|WCAG|aria|스크린\s*리더|screen\s*reader/i,
+ specialist: 'accessibility-specialist',
+ },
+ {
+ pattern: /성능|performance|최적화|optimiz|빠르게|느린|slow|fast|bundle\s*size|로딩/i,
+ specialist: 'performance-specialist',
+ },
+ {
+ pattern: /다국어|i18n|internationalization|번역|locale|translation|localization/i,
+ specialist: 'i18n-specialist',
+ },
+ {
+ pattern: /SEO|검색\s*엔진|search\s*engine|메타|meta\s*tag|sitemap|구조화\s*데이터/i,
+ specialist: 'seo-specialist',
+ },
+ {
+ pattern: /문서화|document|README|API\s*문서|JSDoc|주석|comment/i,
+ specialist: 'documentation-specialist',
+ },
+ {
+ pattern: /UI|UX|디자인|design\s*system|사용자\s*경험|user\s*experience|인터랙션/i,
+ specialist: 'ui-ux-designer',
+ },
+ {
+ pattern:
+ /외부\s*서비스|external\s*(api|service)|webhook|웹훅|third-?party|circuit\s*breaker|retry\s*pattern|API\s*integration|서드파티|연동|SDK\s*wrapper/i,
+ specialist: 'integration-specialist',
+ },
+ {
+ pattern:
+ /observability|관측성|distributed\s*trac|분산\s*추적|SLI|SLO|error\s*budget|OpenTelemetry|otel|Prometheus|Grafana|Jaeger|Zipkin|log\s*aggregat|로그\s*수집|alerting\s*strateg|알림\s*전략|메트릭\s*수집|metric\s*collect|tracing\s*infra|monitoring|대시보드|dashboard|logs?\s*manag/i,
+ specialist: 'observability-specialist',
+ },
+ {
+ pattern:
+ /event[- ]?driven|이벤트\s*기반|message\s*queue|메시지\s*큐|Kafka|RabbitMQ|SQS|Azure\s*Service\s*Bus|event\s*sourc|CQRS|saga\s*pattern|분산\s*트랜잭션|distributed\s*transaction|pub\/?sub|dead\s*letter|DLQ|websocket|SSE|server[- ]?sent|real[- ]?time|실시간|async\s*messag|비동기\s*통신/i,
+ specialist: 'event-architecture-specialist',
+ },
+ {
+ pattern:
+ /migration|마이그레이션|migrate|이전|legacy\s*(system|code|moderniz)|레거시|upgrade\s*(framework|version|library)|업그레이드|strangler\s*fig|branch\s*by\s*abstraction|blue[- ]?green|canary\s*(deploy|release)|rollback|롤백|api\s*version|deprecat|dual[- ]?write|backward\s*compatib|호환성|zero[- ]?downtime|data\s*migration|데이터\s*마이그레이션|schema\s*migration|스키마\s*변경|cutover|전환/i,
+ specialist: 'migration-specialist',
+ },
+];
+
+/** Map specialist IDs to domain names */
+const SPECIALIST_DOMAIN_MAP: Record = {
+ 'security-specialist': 'security',
+ 'accessibility-specialist': 'accessibility',
+ 'performance-specialist': 'performance',
+ 'i18n-specialist': 'i18n',
+ 'seo-specialist': 'seo',
+ 'documentation-specialist': 'documentation',
+ 'ui-ux-designer': 'ui-ux',
+ 'integration-specialist': 'integration',
+ 'observability-specialist': 'observability',
+ 'event-architecture-specialist': 'event-architecture',
+ 'migration-specialist': 'migration',
+ 'architecture-specialist': 'architecture',
+ 'test-strategy-specialist': 'testing',
+ 'code-quality-specialist': 'code-quality',
+};
+
+/** Minimal shape of keyword-modes.json for specialist extraction */
+interface ModeConfigSlice {
+ defaultSpecialists?: string[];
+}
+
+/**
+ * One-shot entry point for collective intelligence workflow.
+ *
+ * Combines rule loading, primary agent resolution, specialist recommendation,
+ * and prompt generation in a single call — replacing the multi-step
+ * parse_mode + dispatch_agents ceremony with ~70% token reduction.
+ *
+ * Designed to work with Claude native Teams for real-time specialist debate.
+ */
+@Injectable()
+export class ActivateHandler extends AbstractHandler {
+ private readonly logger = new Logger(ActivateHandler.name);
+
+ constructor(
+ @Inject(KEYWORD_SERVICE) private readonly keywordService: KeywordService,
+ private readonly agentService: AgentService,
+ private readonly rulesService: RulesService,
+ private readonly teamsCapability: TeamsCapabilityService,
+ ) {
+ super();
+ }
+
+ protected getHandledTools(): string[] {
+ return ['activate'];
+ }
+
+ protected async handleTool(
+ toolName: string,
+ args: Record | undefined,
+ ): Promise {
+ switch (toolName) {
+ case 'activate':
+ return this.handleActivate(args);
+ default:
+ return createErrorResponse(`Unknown tool: ${toolName}`);
+ }
+ }
+
+ getToolDefinitions(): ToolDefinition[] {
+ return [
+ {
+ name: 'activate',
+ description:
+ 'One-shot entry point for collective intelligence workflow. ' +
+ 'Combines rule loading, primary agent resolution, specialist recommendation, ' +
+ 'and prompt generation in a single call — replacing the multi-step ' +
+ 'parse_mode + dispatch_agents ceremony. Returns everything needed to ' +
+ 'run a specialist council via Claude native Teams.',
+ inputSchema: {
+ type: 'object',
+ properties: {
+ prompt: {
+ type: 'string',
+ description:
+ 'Task description. May start with a mode keyword (PLAN/ACT/EVAL/AUTO) ' +
+ 'which will be auto-detected, or use the explicit mode parameter.',
+ },
+ mode: {
+ type: 'string',
+ enum: ['PLAN', 'ACT', 'EVAL', 'AUTO'],
+ description:
+ 'Explicit workflow mode. If omitted, auto-detected from prompt keywords.',
+ },
+ primaryAgent: {
+ type: 'string',
+ description: 'Explicit primary agent name. If omitted, uses mode default.',
+ },
+ },
+ required: ['prompt'],
+ },
+ },
+ ];
+ }
+
+ private async handleActivate(args: Record | undefined): Promise {
+ const prompt = extractRequiredString(args, 'prompt');
+ if (prompt === null) {
+ return createErrorResponse('Missing required parameter: prompt');
+ }
+
+ // 1. Resolve mode from explicit param or prompt keyword
+ const explicitMode = extractOptionalString(args, 'mode');
+ const { mode, taskPrompt } = this.resolveMode(prompt, explicitMode);
+
+ // 2. Load rules for mode (reuses KeywordService caching)
+ const rules = await this.keywordService.getRulesForMode(mode, 'standard');
+
+ // 3. Resolve primary agent
+ const primaryAgentName =
+ extractOptionalString(args, 'primaryAgent') ?? MODE_DEFAULT_AGENTS[mode];
+ let primaryAgent: {
+ name: string;
+ displayName: string;
+ systemPrompt: string;
+ } | null = null;
+ try {
+ const agentPrompt = await this.agentService.getAgentSystemPrompt(primaryAgentName, {
+ mode,
+ taskDescription: taskPrompt,
+ });
+ primaryAgent = {
+ name: primaryAgentName,
+ displayName: agentPrompt.displayName,
+ systemPrompt: agentPrompt.systemPrompt,
+ };
+ } catch (error) {
+ this.logger.warn(
+ `Failed to resolve primary agent '${primaryAgentName}': ${error instanceof Error ? error.message : 'Unknown'}`,
+ );
+ }
+
+ // 4. Determine specialists (mode defaults + context-aware patterns)
+ const specialists = await this.resolveSpecialists(mode, taskPrompt);
+
+ // 5. Prepare specialist prompts in parallel (full verbosity for Teams usage)
+ const specialistResults: Array<{
+ name: string;
+ displayName: string;
+ prompt: string;
+ domain: string;
+ }> = [];
+ if (specialists.length > 0) {
+ try {
+ const prepared = await this.agentService.prepareParallelAgents(
+ mode,
+ specialists,
+ undefined,
+ taskPrompt,
+ 'full',
+ );
+ for (const agent of prepared.agents) {
+ specialistResults.push({
+ name: agent.id,
+ displayName: agent.displayName,
+ prompt: agent.taskPrompt ?? agent.description ?? '',
+ domain: SPECIALIST_DOMAIN_MAP[agent.id] ?? agent.id,
+ });
+ }
+ } catch (error) {
+ this.logger.warn(
+ `Failed to prepare specialists: ${error instanceof Error ? error.message : 'Unknown'}`,
+ );
+ }
+ }
+
+ // 6. Check Teams capability
+ const teamsStatus = await this.teamsCapability.getStatus();
+
+ // 7. Build lean response
+ return createJsonResponse({
+ mode,
+ rules: rules.map(r => ({ name: r.name, content: r.content })),
+ primaryAgent,
+ specialists: specialistResults,
+ discussion: {
+ format: 'Each specialist: approve|concern|reject + reasoning + suggestedChanges',
+ consensus: 'No rejections = consensus reached',
+ crossReview: "Specialists review each other's opinions",
+ },
+ nativeIntegration: {
+ teams: teamsStatus.available
+ ? 'Use Claude native Teams to run specialists as teammates for real-time debate'
+ : 'Enable Teams via CODINGBUDDY_TEAMS_ENABLED=true or experimental.teamsCoordination config',
+ memory: 'Use Claude Code Memory for context persistence across sessions',
+ orchestration: 'Host manages mode transitions, clarification, permissions natively',
+ },
+ });
+ }
+
+ /**
+ * Resolve mode from explicit parameter or prompt keyword detection.
+ * Supports English and localized keywords (Korean, Japanese, Chinese, Spanish).
+ */
+ private resolveMode(
+ prompt: string,
+ explicitMode: string | undefined,
+ ): { mode: Mode; taskPrompt: string } {
+ if (explicitMode && isValidMode(explicitMode)) {
+ return { mode: explicitMode as Mode, taskPrompt: prompt };
+ }
+
+ const trimmed = prompt.trim();
+ const keywordRegex = /^([^\s::]+)\s*[::]?\s*(.*)$/s;
+ const match = trimmed.match(keywordRegex);
+
+ if (match?.[1]) {
+ const candidate = match[1];
+ const upper = candidate.toUpperCase();
+ const rest = (match[2] ?? '').trim();
+
+ if (KEYWORDS.includes(upper as Mode)) {
+ return { mode: upper as Mode, taskPrompt: rest || trimmed };
+ }
+
+ const localized = LOCALIZED_KEYWORD_MAP[candidate] ?? LOCALIZED_KEYWORD_MAP[upper];
+ if (localized) {
+ return { mode: localized, taskPrompt: rest || trimmed };
+ }
+ }
+
+ return { mode: 'PLAN', taskPrompt: trimmed };
+ }
+
+ /**
+ * Merge mode-default specialists (from keyword-modes.json) with
+ * context-aware specialist detection (from prompt patterns).
+ */
+ private async resolveSpecialists(mode: Mode, prompt: string): Promise {
+ let defaultSpecialists: string[] = [];
+ try {
+ const configContent = await this.rulesService.getRuleContent('keyword-modes.json');
+ const config = JSON.parse(configContent) as { modes: Record };
+ defaultSpecialists = config.modes[mode]?.defaultSpecialists ?? [];
+ } catch {
+ this.logger.debug('Failed to load keyword-modes.json for default specialists');
+ }
+
+ const contextSpecialists = this.getContextAwareSpecialists(prompt);
+ return [...new Set([...defaultSpecialists, ...contextSpecialists])];
+ }
+
+ /**
+ * Detect additional specialists based on prompt content patterns.
+ */
+ private getContextAwareSpecialists(prompt: string): string[] {
+ const specialists: string[] = [];
+ for (const { pattern, specialist } of CONTEXT_SPECIALIST_PATTERNS) {
+ if (pattern.test(prompt)) {
+ specialists.push(specialist);
+ }
+ }
+ return specialists;
+ }
+}
diff --git a/apps/mcp-server/src/mcp/handlers/briefing.handler.ts b/apps/mcp-server/src/mcp/handlers/briefing.handler.ts
index c88421fb..725b186c 100644
--- a/apps/mcp-server/src/mcp/handlers/briefing.handler.ts
+++ b/apps/mcp-server/src/mcp/handlers/briefing.handler.ts
@@ -52,7 +52,7 @@ export class BriefingHandler extends AbstractHandler {
{
name: 'create_briefing',
description:
- 'Capture current session state into a briefing document for cross-session recovery',
+ '[DEPRECATED — Use Claude Code Memory for cross-session context] Capture current session state into a briefing document for cross-session recovery.',
inputSchema: {
type: 'object',
properties: {
diff --git a/apps/mcp-server/src/mcp/handlers/checklist-context.handler.ts b/apps/mcp-server/src/mcp/handlers/checklist-context.handler.ts
index 82fb3979..0a31d7a4 100644
--- a/apps/mcp-server/src/mcp/handlers/checklist-context.handler.ts
+++ b/apps/mcp-server/src/mcp/handlers/checklist-context.handler.ts
@@ -99,7 +99,7 @@ export class ChecklistContextHandler extends AbstractHandler {
{
name: 'analyze_task',
description:
- 'Analyze a task to provide contextual recommendations including risk assessment, relevant checklists, specialist recommendations, and workflow suggestions. Use this at the start of PLAN mode to get comprehensive task analysis.',
+ '[DEPRECATED — Use activate + /dream instead] Analyze a task to provide contextual recommendations including risk assessment, relevant checklists, specialist recommendations, and workflow suggestions.',
inputSchema: {
type: 'object',
properties: {
diff --git a/apps/mcp-server/src/mcp/handlers/context-document.handler.ts b/apps/mcp-server/src/mcp/handlers/context-document.handler.ts
index b403de62..22f255b2 100644
--- a/apps/mcp-server/src/mcp/handlers/context-document.handler.ts
+++ b/apps/mcp-server/src/mcp/handlers/context-document.handler.ts
@@ -58,7 +58,7 @@ export class ContextDocumentHandler extends AbstractHandler {
return [
{
name: 'read_context',
- description: `Read the current context document from ${CONTEXT_FILE_PATH}. Returns all accumulated context from PLAN/ACT/EVAL modes including decisions, notes, and recommended agents. Supports verbosity levels for controlling returned data size.`,
+ description: `[DEPRECATED — Use Claude Code Memory instead for cross-session context persistence] Read the current context document from ${CONTEXT_FILE_PATH}. Returns all accumulated context from PLAN/ACT/EVAL modes including decisions, notes, and recommended agents. Supports verbosity levels for controlling returned data size.`,
inputSchema: {
type: 'object',
properties: {
@@ -79,7 +79,7 @@ export class ContextDocumentHandler extends AbstractHandler {
},
{
name: 'update_context',
- description: `MANDATORY: Update the context document at ${CONTEXT_FILE_PATH}.
+ description: `[DEPRECATED — Use Claude Code Memory instead for cross-session context persistence] Update the context document at ${CONTEXT_FILE_PATH}.
- PLAN mode: Resets (clears) existing content and starts fresh.
- ACT/EVAL modes: Appends new section to existing content (requires PLAN first).
- Automatic cleanup: If document exceeds size threshold, older sections are automatically summarized.
diff --git a/apps/mcp-server/src/mcp/handlers/discussion.handler.spec.ts b/apps/mcp-server/src/mcp/handlers/discussion.handler.spec.ts
index 7501ec15..ec478b3e 100644
--- a/apps/mcp-server/src/mcp/handlers/discussion.handler.spec.ts
+++ b/apps/mcp-server/src/mcp/handlers/discussion.handler.spec.ts
@@ -112,9 +112,8 @@ describe('DiscussionHandler', () => {
const data = JSON.parse(result!.content[0].text) as ExperimentalDiscussionResult;
expect(data.experimental).toBe(true);
expect(data.warning).toBe(EXPERIMENTAL_DISCUSSION_WARNING);
- expect(data.warning).toContain('experimental');
- expect(data.warning).toContain('templated synthesis');
- expect(data.warning).toContain('not real specialist execution');
+ expect(data.warning).toContain('synthesis');
+ expect(data.warning).toContain('activate');
});
it('should return error for missing topic', async () => {
@@ -300,12 +299,12 @@ describe('DiscussionHandler', () => {
expect(definitions[0].name).toBe('agent_discussion');
});
- it('should mark tool description as experimental', () => {
+ it('should describe collective intelligence and activation guidance', () => {
const definitions = handler.getToolDefinitions();
const description = definitions[0].description.toLowerCase();
- expect(description).toContain('experimental');
- expect(description).toContain('templated synthesis');
+ expect(description).toContain('specialist');
+ expect(description).toContain('activate');
expect(description).toContain(EXPERIMENTAL_DISCUSSION_ENV.toLowerCase());
});
diff --git a/apps/mcp-server/src/mcp/handlers/discussion.handler.ts b/apps/mcp-server/src/mcp/handlers/discussion.handler.ts
index e39405ba..481ccb9d 100644
--- a/apps/mcp-server/src/mcp/handlers/discussion.handler.ts
+++ b/apps/mcp-server/src/mcp/handlers/discussion.handler.ts
@@ -44,16 +44,13 @@ const SEVERITY_ORDER: readonly OpinionSeverity[] = ['info', 'low', 'medium', 'hi
/**
* Handler for the agent_discussion tool.
*
- * EXPERIMENTAL — disabled by default. Current output is templated synthesis of
- * specialist opinions rather than real specialist execution, so it does NOT
- * represent collective intelligence from live agents. The tool returns a
- * {@link DisabledDiscussionResult} unless the caller explicitly opts in via
- * `CODINGBUDDY_EXPERIMENTAL_DISCUSSION=1`, in which case it returns an
- * {@link ExperimentalDiscussionResult} that carries a warning banner so
- * consumers cannot mistake the output for a real multi-agent debate.
+ * Produces structured specialist opinions for collective intelligence workflows.
+ * In Claude Code environments with native Teams support, use the `activate` tool
+ * to run real specialist agents as teammates for live debate. This tool provides
+ * a structured discussion format that can seed or complement Teams-based review.
*
- * A follow-up effort should rebuild this on top of real specialist dispatch;
- * until then callers should prefer `dispatch_agents` for actual expert input.
+ * When `CODINGBUDDY_EXPERIMENTAL_DISCUSSION=1` is NOT set, the tool returns
+ * guidance on using `activate` + Claude native Teams for real specialist execution.
*/
@Injectable()
export class DiscussionHandler extends AbstractHandler {
@@ -82,12 +79,11 @@ export class DiscussionHandler extends AbstractHandler {
{
name: 'agent_discussion',
description:
- '[EXPERIMENTAL — disabled by default] Produces templated synthesis of ' +
- 'specialist opinions, not real specialist execution. The output does ' +
- 'not reflect collective intelligence from live agents; treat it as a ' +
- 'placeholder until the rebuild lands. Enable by setting ' +
- `${EXPERIMENTAL_DISCUSSION_ENV}=1. When disabled, the tool returns ` +
- '{disabled: true} without invoking synthesis.',
+ 'Structured specialist discussion for collective intelligence workflows. ' +
+ 'Collects and synthesizes opinions from multiple specialist agents on a topic. ' +
+ 'For real-time specialist debate, use the `activate` tool with Claude native Teams. ' +
+ `Set ${EXPERIMENTAL_DISCUSSION_ENV}=1 to enable built-in synthesis. ` +
+ 'When unset, returns guidance on using activate + Teams instead.',
inputSchema: {
type: 'object',
properties: {
diff --git a/apps/mcp-server/src/mcp/handlers/discussion.types.ts b/apps/mcp-server/src/mcp/handlers/discussion.types.ts
index 59539f69..fed7f2c1 100644
--- a/apps/mcp-server/src/mcp/handlers/discussion.types.ts
+++ b/apps/mcp-server/src/mcp/handlers/discussion.types.ts
@@ -72,17 +72,20 @@ export const VALID_SEVERITIES: readonly OpinionSeverity[] = [
export const EXPERIMENTAL_DISCUSSION_ENV = 'CODINGBUDDY_EXPERIMENTAL_DISCUSSION';
/**
- * Warning banner attached to any enabled agent_discussion response so callers
- * cannot mistake templated synthesis for real specialist execution.
+ * Warning banner attached to any enabled agent_discussion response.
+ * Indicates that results are from built-in synthesis, not live agent execution.
+ * For real specialist debate, use activate + Claude native Teams.
*/
export const EXPERIMENTAL_DISCUSSION_WARNING =
- '\u26a0\ufe0f experimental — templated synthesis, not real specialist execution';
+ 'Built-in synthesis — for real specialist debate, use activate + Claude native Teams';
/**
* Reason surfaced when the tool is disabled (default state).
+ * Guides users toward activate + Claude native Teams for real specialist execution.
*/
export const DISABLED_DISCUSSION_REASON =
- 'templated synthesis not aligned with collective intelligence promise';
+ 'Use the `activate` tool with Claude native Teams for real specialist debate. ' +
+ 'Set CODINGBUDDY_EXPERIMENTAL_DISCUSSION=1 to enable built-in synthesis as an alternative.';
/**
* Response returned when the agent_discussion tool is disabled (default).
diff --git a/apps/mcp-server/src/mcp/handlers/index.ts b/apps/mcp-server/src/mcp/handlers/index.ts
index 03ce799c..acef0cb0 100644
--- a/apps/mcp-server/src/mcp/handlers/index.ts
+++ b/apps/mcp-server/src/mcp/handlers/index.ts
@@ -168,6 +168,12 @@ export { RuleImpactHandler } from './rule-impact.handler';
*/
export { ReviewPrHandler } from './review-pr.handler';
+/**
+ * Handler for activate tool (one-shot collective intelligence entry point)
+ * @see {@link ActivateHandler}
+ */
+export { ActivateHandler } from './activate.handler';
+
/**
* Injection token for the array of all tool handlers.
*
diff --git a/apps/mcp-server/src/mcp/handlers/resume.handler.ts b/apps/mcp-server/src/mcp/handlers/resume.handler.ts
index eff41da1..af6fff49 100644
--- a/apps/mcp-server/src/mcp/handlers/resume.handler.ts
+++ b/apps/mcp-server/src/mcp/handlers/resume.handler.ts
@@ -47,7 +47,8 @@ export class ResumeHandler extends AbstractHandler {
return [
{
name: 'resume_session',
- description: 'Load a previous session briefing to restore context and continue work',
+ description:
+ '[DEPRECATED — Use Claude Code Memory for session resume] Load a previous session briefing to restore context and continue work.',
inputSchema: {
type: 'object',
properties: {
diff --git a/apps/mcp-server/src/mcp/mcp.module.ts b/apps/mcp-server/src/mcp/mcp.module.ts
index 3665f89a..553e5c92 100644
--- a/apps/mcp-server/src/mcp/mcp.module.ts
+++ b/apps/mcp-server/src/mcp/mcp.module.ts
@@ -43,6 +43,7 @@ import {
BriefingHandler,
ResumeHandler,
RuleImpactHandler,
+ ActivateHandler,
} from './handlers';
const handlers = [
@@ -68,6 +69,7 @@ const handlers = [
BriefingHandler,
ResumeHandler,
RuleImpactHandler,
+ ActivateHandler,
];
@Module({
diff --git a/packages/rules/.ai-rules/adapters/claude-code.md b/packages/rules/.ai-rules/adapters/claude-code.md
index 4608eb45..441947c9 100644
--- a/packages/rules/.ai-rules/adapters/claude-code.md
+++ b/packages/rules/.ai-rules/adapters/claude-code.md
@@ -6,6 +6,52 @@ This guide explains how to use the common AI rules (`.ai-rules/`) in Claude Code
Claude Code uses the `.claude/` directory for project-specific custom instructions, referencing the common rules from `.ai-rules/`.
+## Collective Intelligence with `activate` + Claude Native Teams
+
+### The `activate` Tool (Recommended Entry Point)
+
+The `activate` MCP tool is the **one-shot entry point** for collective intelligence workflows in Claude Code. It replaces the multi-step `parse_mode` + `dispatch_agents` ceremony with a single call.
+
+```
+activate({ prompt: "design auth feature", mode: "PLAN" })
+```
+
+**Returns:**
+- `mode` — resolved workflow mode
+- `rules` — loaded rules for the mode
+- `primaryAgent` — agent name + full system prompt
+- `specialists` — recommended specialists with full prompts
+- `discussion` — format guide for approve/concern/reject consensus
+- `nativeIntegration` — guidance for Teams, Memory, orchestration
+
+### Running a Specialist Council via Claude Native Teams
+
+When `activate` returns specialists, use Claude native Teams for real-time debate:
+
+```
+1. activate({ prompt }) → get specialists
+2. TeamCreate({ team_name: "plan-council" })
+3. For each specialist: Agent({ team_name, name: specialist.name, prompt: specialist.prompt })
+4. Specialists analyze independently → cross-review → consensus
+5. Collect findings → summarize to user
+```
+
+### Claude Code Native Feature Mapping
+
+Use Claude Code native features instead of legacy codingbuddy tools:
+
+| Need | Use This | Instead of |
+|------|----------|------------|
+| Workflow entry | `activate` | `parse_mode` + `dispatch_agents` |
+| Cross-session context | Claude Code Memory | `update_context` / `create_briefing` / `resume_session` |
+| Specialist execution | Claude native Teams | subagent dispatch |
+| Task exploration | `/dream` | `analyze_task` |
+| Planning approval | `EnterPlanMode` | planning stage routing |
+| Repeated execution | `/loop` | AUTO mode repetition |
+| Clarification | `AskUserQuestion` | clarification gate |
+
+> **Note**: `parse_mode` remains available for non-Claude Code hosts (Cursor, Codex, etc.).
+
## 🆕 Code Conventions Support
CodingBuddy now automatically enforces project code conventions from config files:
@@ -325,9 +371,13 @@ AI assistants should display the `activation_message.formatted` field at the sta
CodingBuddy supports parallel execution of multiple specialist agents for comprehensive analysis.
-### When to Use Parallel Execution
+### Recommended: Claude Native Teams (Primary Strategy)
+
+In Claude Code environments, use **Claude native Teams** as the primary execution strategy for specialist councils. The `activate` tool returns specialist prompts ready for Teams execution. See the "Collective Intelligence with `activate`" section above for the full workflow.
+
+### Legacy: SubAgent / TaskMaestro Strategies
-Parallel execution is recommended when `parse_mode` returns a `parallelAgentsRecommendation` field:
+For non-Claude Code hosts or when Teams is not available, parallel execution is recommended when `parse_mode` returns a `parallelAgentsRecommendation` field:
| Mode | Default Specialists | Use Case |
|------|---------------------|----------|