---
title: "feat: 私董会讨论模式（Board Meeting Mode）"
type: feat
status: completed
created: 2026-06-17
origin: docs/brainstorms/2026-06-17-board-meeting-mode-requirements.md
---

# Plan: 私董会讨论模式（Board Meeting Mode）

**Origin**: `docs/brainstorms/2026-06-17-board-meeting-mode-requirements.md`
**Depth**: Deep
**Created**: 2026-06-17

---

## Summary

为 Fischer AgentKit 新增私董会讨论模式，与现有 hub-and-spoke 任务分解模式并列。用户通过 `@board` 前缀触发，指定预设名人专家（如马斯克、贝佐斯、张小龙），针对决策类问题进行多轮自主循环讨论。每轮全员并行发言 + 主持人小结，达到最大轮次后主持人给出最终决策建议。整个过程以群聊形式呈现，用户可随时干预。

---

## Problem Frame

当前专家团功能（`src/agentkit/experts/`）采用 hub-and-spoke 模式，仅支持任务分解执行，无群聊式讨论能力。且该功能未集成到主聊天流程（`chat.py:584-590` 中 `TEAM_COLLAB` 回退到 REACT）。用户希望就决策类问题召集名人专家团进行多视角讨论，获得综合建议。

**核心问题**：
1. 无预设名人专家库（`configs/experts/` 不存在）
2. 无自主循环讨论机制（现有模式是任务分解，非群聊讨论）
3. 专家团功能未集成到主聊天 WebSocket 流程

---

## Requirements

本计划实现需求文档中的以下功能需求（FR-1 到 FR-15）：

- **FR-1/FR-2**: `@board` 前缀路由，与 `@team` 共存
- **FR-3**: 预设 5-8 位名人专家 YAML
- **FR-4**: `ExpertConfig` 扩展（`speaking_style`、`decision_framework`）
- **FR-5**: 默认私董会模板 `private_board`
- **FR-6**: `BoardTeam` 容器（`BoardStatus` 生命周期）
- **FR-7**: `BoardOrchestrator` 讨论引擎（开场→循环讨论→总结）
- **FR-8**: 讨论历史管理（含压缩）
- **FR-9**: 终止条件（最大轮次 + 用户干预 + 异常）
- **FR-10/FR-11**: WebSocket 事件（5 个新事件）+ 广播
- **FR-12/FR-13/FR-14**: 前端群聊式 UI + 状态展示 + 干预输入
- **FR-15**: `agentkit.yaml` 配置项

**成功标准**（见需求文档 §7）：
- `@board:elon_musk,jeff_bezos 讨论主题` 能触发讨论
- 每轮专家并行发言，主持人小结
- 达到最大轮次后主持人给出最终决策建议
- 用户可随时插入消息影响讨论
- 前端以群聊形式展示
- 单元测试覆盖率 ≥ 80%

---

## Key Technical Decisions

### KTD-1: 独立模块而非扩展现有 ExpertTeam

**决策**: 新建 `board.py`、`board_orchestrator.py`、`board_router.py`，不修改现有 `team.py`、`orchestrator.py`、`router.py`。

**理由**: 私董会讨论模式（多轮群聊）与 hub-and-spoke（任务分解执行）的执行流程完全不同。独立模块职责清晰，避免语义混淆，符合需求文档"新增并列模式"决策。

**复用**: `ExpertConfig`（扩展）、`Expert`（运行时包装器）、`AgentPool`、`HandoffTransport`、`SharedWorkspace`、`ExpertTemplateRegistry`。

### KTD-2: 讨论历史结构

**决策**: 使用 `list[dict]` 结构存储讨论历史，每条记录包含 `round`、`expert_name`、`content`、`timestamp`、`role`（expert/moderator/user）。

**理由**: 简单的列表结构易于序列化和注入到 LLM prompt。主持人小结也作为历史记录，角色为 `moderator`。用户干预消息角色为 `user`。

**压缩策略**: 当历史 token 数超过阈值（默认 4000）时，主持人先压缩历史（保留每轮关键观点），再继续下一轮。压缩 prompt 在实现时细化。

### KTD-3: 并行发言生成

**决策**: 使用 `asyncio.gather` 并行生成所有非主持人专家的发言，然后按专家列表顺序追加到历史和广播事件。

**理由**: 并行生成提高效率（5 专家并行 vs 串行）。前端展示顺序按配置顺序，即使并行生成也按顺序追加到 UI。

### KTD-4: 主持人角色

**决策**: 主持人默认为首位专家，通过 `ExpertConfig.is_lead=True` 标识。主持人负责开场介绍、每轮小结、最终总结。

**理由**: 复用现有 `is_lead` 字段，无需引入新角色。主持人也是名人专家之一，其发言风格由其 persona 决定。

### KTD-5: WebSocket 事件复用与扩展

**决策**: 新增 5 个事件类型（`board_started`、`expert_speech`、`round_summary`、`user_intervention`、`board_concluded`），加入现有 `_VALID_TEAM_EVENT_TYPES` 集合。复用 `emit_team_event()` 辅助函数推送。

**理由**: 现有 `emit_team_event()` 已定义但未被调用，本期同时完成其调用集成。事件类型加入现有集合，复用验证逻辑。

### KTD-6: 配置加载

**决策**: 在 `app.py` 启动时，类似 skills 加载，从 `configs/experts/` 目录加载所有专家 YAML 到 `ExpertTemplateRegistry`，挂载到 `app.state.expert_template_registry`。

**理由**: 复用 `ExpertTemplateRegistry.load_from_directory()` 方法。与 skills 加载模式一致，保持架构一致性。

---

## High-Level Technical Design

### 组件关系图

```mermaid
graph TB
    User[用户输入 @board:experts 主题]
    Router[BoardRouter]
    Registry[ExpertTemplateRegistry]
    Team[BoardTeam]
    Orchestrator[BoardOrchestrator]
    Expert1[Expert: 马斯克]
    Expert2[Expert: 贝佐斯]
    Expert3[Expert: 张小龙]
    Transport[HandoffTransport]
    ChatWS[chat.py WebSocket]
    Frontend[前端群聊 UI]

    User --> Router
    Router --> Registry
    Registry --> Team
    Team --> Orchestrator
    Orchestrator --> Expert1
    Orchestrator --> Expert2
    Orchestrator --> Expert3
    Expert1 --> Transport
    Expert2 --> Transport
    Expert3 --> Transport
    Transport --> ChatWS
    ChatWS --> Frontend
```

### 讨论流程状态机

```mermaid
stateDiagram-v2
    [*] --> FORMING: @board 触发
    FORMING --> DISCUSSING: 专家创建完成
    DISCUSSING --> DISCUSSING: 每轮发言+小结
    DISCUSSING --> CONCLUDING: 达到最大轮次/用户停止
    DISCUSSING --> DISSOLVED: 异常终止
    CONCLUDING --> COMPLETED: 主持人最终总结
    COMPLETED --> DISSOLVED: 资源回收
    DISSOLVED --> [*]
```

### 单轮讨论时序图

```mermaid
sequenceDiagram
    participant O as BoardOrchestrator
    participant E1 as Expert 1
    participant E2 as Expert 2
    participant M as Moderator
    participant T as Transport
    participant WS as WebSocket

    O->>WS: board_started 事件
    O->>M: 开场介绍请求
    M->>T: 发言内容
    T->>WS: expert_speech (moderator)
    
    loop 每轮讨论
        par 并行生成发言
            O->>E1: 发言请求(历史+角色prompt)
            E1-->>O: 发言内容
        and
            O->>E2: 发言请求(历史+角色prompt)
            E2-->>O: 发言内容
        end
        O->>T: 广播 E1 发言
        T->>WS: expert_speech (E1)
        O->>T: 广播 E2 发言
        T->>WS: expert_speech (E2)
        O->>M: 小结请求(本轮发言)
        M-->>O: 小结内容
        O->>T: 广播小结
        T->>WS: round_summary
    end
    
    O->>M: 最终总结请求
    M-->>O: 决策建议
    O->>WS: board_concluded 事件
```

---

## Scope Boundaries

### In Scope

- `BoardTeam`、`BoardOrchestrator`、`BoardRouter` 新模块
- `configs/experts/` 预设名人 YAML（8 位）
- `ExpertConfig` 扩展（`speaking_style`、`decision_framework`）
- WebSocket 事件（5 个新事件）+ `emit_team_event()` 调用集成
- 前端群聊式展示增强 + 事件处理
- 主聊天流程集成（`chat.py` 接入 `BoardRouter`）
- `app.py` 启动加载专家配置
- `agentkit.yaml` 配置项
- 单元测试覆盖

### Deferred to Follow-Up Work

- 集成外部蒸馏工具（colleague.skill/nuwa-skill）
- LLM 自动蒸馏生成名人 SOUL
- 共识检测自动终止（置信度/投票）
- 技术评审/创意脑暴场景
- Expert Team Canvas 式可视化
- 专家间直接通信（辩论模式）
- 语音/视频输出
- 历史讨论回顾与检索
- 修复 `@team` 在 `chat.py` 的集成缺口（独立任务）

### Outside This Product's Identity

- 实时名人数据更新
- 名人本人授权或验证
- 娱乐向角色扮演

---

## Implementation Units

### U1. 扩展 ExpertConfig 新增讨论模式字段

**Goal**: 为 `ExpertConfig` 新增 `speaking_style` 和 `decision_framework` 字段，支持名人专家的个性化表达和决策框架。

**Requirements**: FR-4

**Dependencies**: 无

**Files**:
- `src/agentkit/experts/config.py` — 修改 `ExpertConfig.__init__`、`from_dict`、`to_dict`
- `tests/unit/experts/test_config.py` — 新增字段测试

**Approach**:
- 在 `ExpertConfig.__init__` 新增 `speaking_style: str = ""` 和 `decision_framework: str = ""` 参数
- 在 `from_dict` 中读取 `data.get("speaking_style", "")` 和 `data.get("decision_framework", "")`
- 在 `to_dict` 中序列化这两个字段
- 字段有默认值，向后兼容现有 `@team` 模式和动态生成的 ExpertConfig

**Patterns to follow**: 现有 `persona`、`thinking_style` 字段的实现模式（`src/agentkit/experts/config.py:35-65`）

**Test scenarios**:
- **Happy path**: 创建 ExpertConfig 时传入 speaking_style 和 decision_framework，验证字段值正确
- **Happy path**: 从 dict 创建 ExpertConfig，包含 speaking_style 和 decision_framework，验证字段值正确
- **Edge case**: 不传 speaking_style 和 decision_framework，验证默认值为空字符串
- **Edge case**: to_dict 输出包含 speaking_style 和 decision_framework 字段
- **Integration**: 现有 ExpertConfig 用法（不传新字段）仍正常工作

**Verification**: `pytest tests/unit/experts/test_config.py` 通过，现有测试不受影响

---

### U2. 创建预设名人专家 YAML 库

**Goal**: 在 `configs/experts/` 目录下创建 8 位名人专家 YAML 文件，每位名人包含 persona、thinking_style、speaking_style、decision_framework 等字段。

**Requirements**: FR-3, FR-5

**Dependencies**: U1

**Files**:
- `configs/experts/elon_musk.yaml`
- `configs/experts/jeff_bezos.yaml`
- `configs/experts/allenzhang.yaml`
- `configs/experts/charlie_munger.yaml`
- `configs/experts/paul_graham.yaml`
- `configs/experts/steve_jobs.yaml`
- `configs/experts/warren_buffett.yaml`
- `configs/experts/ray_dalio.yaml`
- `configs/experts/private_board.yaml` — 默认私董会模板（引用上述专家）

**Approach**:
- 每个 YAML 遵循 `ExpertTemplateRegistry.load_from_yaml` 的格式（见 `src/agentkit/experts/registry.py:71-87`）
- 字段：`name`、`description`、`is_builtin: true`、`config`（含 `name`、`agent_type: expert`、`persona`、`thinking_style`、`speaking_style`、`decision_framework`、`avatar`、`color`、`is_lead: false`、`task_mode: llm_generate`、`prompt.identity`）
- `private_board.yaml` 是一个特殊的"团队模板"，定义默认专家组合（3-5 位），格式为 `name: private_board`、`members: [elon_musk, jeff_bezos, allenzhang, charlie_munger, paul_graham]`
- 名人 persona 内容需体现其标志性思维模式：
  - 马斯克：第一性原理、物理思维、激进创新
  - 贝佐斯：Day 1 思维、客户至上、长期主义
  - 张小龙：用户体验、极简主义、社交产品直觉
  - 芒格：心智模型、跨学科思维、逆向思考
  - Paul Graham：创业、做用户想要的东西、反从众
  - 乔布斯：产品设计、现实扭曲力场、专注
  - 巴菲特：价值投资、能力圈、复利思维
  - Ray Dalio：原则驱动决策、极度透明

**Patterns to follow**: `src/agentkit/experts/registry.py:71-87` 的 YAML 格式示例

**Test scenarios**:
- **Test expectation**: none — YAML 配置文件，由 U9 的集成测试覆盖加载逻辑

**Verification**: `ExpertTemplateRegistry.load_from_directory("configs/experts/")` 能成功加载所有 8 位专家 + 1 个团队模板

---

### U3. 实现 BoardRouter @board 前缀路由

**Goal**: 实现 `BoardRouter` 类，解析 `@board` 前缀，支持指定专家或使用默认私董会模板。

**Requirements**: FR-1, FR-2

**Dependencies**: U1, U2

**Files**:
- `src/agentkit/experts/board_router.py` — 新建
- `tests/unit/experts/test_board_router.py` — 新建

**Approach**:
- 参考 `ExpertTeamRouter`（`src/agentkit/experts/router.py`）的实现模式
- 正则匹配 `@board` 前缀：`^@board(?::(\S+))?\s*(.*)` 
- 支持两种格式：
  - `@board:elon_musk,jeff_bezos 讨论主题` — 指定专家
  - `@board 讨论主题` — 使用默认 `private_board` 模板
- 专家名验证：复用 `_EXPERT_NAME_RE = re.compile(r"^[a-zA-Z0-9_-]{1,64}$")`
- 最多 10 位专家（`MAX_EXPERTS = 10`）
- 返回 `BoardRoutingResult` dataclass：`matched`、`board_mode`、`specified_experts`、`topic`、`use_default_template`
- `resolve_expert_configs()` 方法：从 `ExpertTemplateRegistry` 解析专家名到 `ExpertConfig` 列表，首位设为 `is_lead=True`（主持人）
- 如果指定 `private_board`，从 `private_board.yaml` 加载成员列表
- 未识别的专家名：记录警告，动态创建基本 ExpertConfig

**Patterns to follow**: `src/agentkit/experts/router.py` 的 `ExpertTeamRouter` 实现

**Test scenarios**:
- **Happy path**: `@board:elon_musk,jeff_bezos 讨论主题` → matched=True, specified_experts=["elon_musk", "jeff_bezos"], topic="讨论主题"
- **Happy path**: `@board 讨论主题` → matched=True, use_default_template=True, topic="讨论主题"
- **Happy path**: `@board:private_board 讨论主题` → matched=True, 加载 private_board 成员列表
- **Edge case**: `@board` 无主题 → matched=True, topic 为空
- **Edge case**: 专家名超过 10 个 → 截断到 10 个
- **Error path**: 无效专家名（含特殊字符）→ 过滤掉无效名，记录警告
- **Error path**: 指定不存在的专家 → 动态创建基本 ExpertConfig
- **Integration**: `resolve_expert_configs()` 返回的列表首位 is_lead=True

**Verification**: `pytest tests/unit/experts/test_board_router.py` 通过

---

### U4. 实现 BoardTeam 容器

**Goal**: 实现 `BoardTeam` 容器，管理私董会的专家生命周期、讨论状态和事件广播。

**Requirements**: FR-6, FR-8

**Dependencies**: U1

**Files**:
- `src/agentkit/experts/board.py` — 新建（`BoardTeam`、`BoardStatus`、`DiscussionHistory`）
- `tests/unit/experts/test_board.py` — 新建

**Approach**:
- 参考 `ExpertTeam`（`src/agentkit/experts/team.py`）的容器模式
- `BoardStatus` 枚举：`FORMING` → `DISCUSSING` → `CONCLUDING` → `COMPLETED` → `DISSOLVED`
- `BoardTeam` 持有：
  - `team_id`、`topic`、`experts: dict[str, Expert]`、`moderator_name: str`
  - `history: list[dict]` — 讨论历史（每条含 round、expert_name、content、timestamp、role）
  - `current_round: int`、`max_rounds: int`
  - `_handoff_transport`、`_workspace`、`_pool`、`_team_channel`
- `create_board()` 方法：创建主持人和成员专家，注入 board_context 到 system prompt
- `_build_board_context()` 方法：构建私董会上下文（强调群聊讨论模式、角色差异、讨论规则）
- `add_to_history()` 方法：追加发言到历史
- `get_history_text()` 方法：返回格式化的历史文本用于 LLM prompt
- `compress_history()` 方法：主持人压缩历史（超过阈值时）
- `broadcast_user_message()` 方法：广播用户干预消息
- `dissolve()` 方法：解散团队，回收资源
- 复用 `Expert.create()`、`HandoffTransport`、`SharedWorkspace`

**Patterns to follow**: `src/agentkit/experts/team.py` 的 `ExpertTeam` 容器模式

**Technical design** (directional):
```python
class BoardStatus(str, enum.Enum):
    FORMING = "forming"
    DISCUSSING = "discussing"
    CONCLUDING = "concluding"
    COMPLETED = "completed"
    DISSOLVED = "dissolved"

class BoardTeam:
    async def create_board(self, topic: str, expert_configs: list[ExpertConfig], max_rounds: int) -> None
    async def add_to_history(self, round: int, expert_name: str, content: str, role: str) -> None
    def get_history_text(self, up_to_round: int | None = None) -> str
    async def compress_history(self, moderator: Expert) -> None
    async def broadcast_user_message(self, content: str) -> None
    async def dissolve(self) -> None
```

**Test scenarios**:
- **Happy path**: `create_board()` 创建主持人和成员，状态变为 DISCUSSING
- **Happy path**: `add_to_history()` 追加发言，`get_history_text()` 返回格式化文本
- **Edge case**: 空历史时 `get_history_text()` 返回空字符串
- **Edge case**: `compress_history()` 超过阈值时压缩，未超过时不操作
- **Integration**: `broadcast_user_message()` 通过 handoff_transport 发送事件
- **Integration**: `dissolve()` 清理所有专家，状态变为 DISSOLVED
- **Error path**: 未配置 AgentPool 时 `create_board()` 抛出 RuntimeError

**Verification**: `pytest tests/unit/experts/test_board.py` 通过

---

### U5. 实现 BoardOrchestrator 讨论引擎

**Goal**: 实现 `BoardOrchestrator`，驱动私董会讨论流程：开场 → 多轮并行发言 + 主持人小结 → 最终决策建议。

**Requirements**: FR-7, FR-9

**Dependencies**: U4

**Files**:
- `src/agentkit/experts/board_orchestrator.py` — 新建
- `tests/unit/experts/test_board_orchestrator.py` — 新建

**Approach**:
- 参考 `TeamOrchestrator`（`src/agentkit/experts/orchestrator.py`）的执行引擎模式
- `execute(topic)` 主入口流程：
  1. 广播 `board_started` 事件
  2. 主持人开场介绍（介绍议题、讨论规则）
  3. 循环 `max_rounds` 轮：
     - 并行生成所有非主持人专家发言（`asyncio.gather`）
     - 每个专家发言基于：角色 persona + thinking_style + speaking_style + decision_framework + 完整讨论历史 + 当前轮次/最大轮次
     - 按专家列表顺序广播 `expert_speech` 事件
     - 主持人小结本轮要点，广播 `round_summary` 事件
     - 检查用户干预消息（通过 handoff_transport 或共享状态）
     - 检查历史 token 长度，超过阈值时压缩
  4. 主持人最终总结（决策建议、共识点、分歧点），广播 `board_concluded` 事件
- `_generate_expert_speech()` 方法：构建专家发言 prompt，调用 LLM
- `_generate_moderator_summary()` 方法：构建主持人小结 prompt，调用 LLM
- `_generate_final_conclusion()` 方法：构建最终总结 prompt，调用 LLM
- `_check_user_intervention()` 方法：检查是否有用户干预消息
- `_handle_stop_command()` 方法：处理用户 `/stop` 命令
- 复用 `_get_llm_gateway()` 和 `_broadcast_event()` 模式（来自 TeamOrchestrator）
- 异常处理：LLM 不可用时，主持人用已有历史总结；所有专家发言失败时，提前进入总结阶段

**Patterns to follow**: `src/agentkit/experts/orchestrator.py` 的 `TeamOrchestrator` 执行模式

**Technical design** (directional):
```python
class BoardOrchestrator:
    def __init__(self, team: BoardTeam) -> None
    
    async def execute(self, topic: str) -> dict[str, Any]
    # Returns: {status, summary, decision_advice, total_rounds, consensus_points, dissent_points}
    
    async def _generate_expert_speech(self, expert: Expert, round: int) -> str
    async def _generate_moderator_summary(self, round: int) -> str
    async def _generate_final_conclusion(self) -> dict[str, Any]
    async def _check_user_intervention(self) -> str | None
```

**Test scenarios**:
- **Happy path**: `execute()` 完成完整讨论流程，返回 status="completed"
- **Happy path**: 每轮生成 N-1 个专家发言 + 1 个主持人小结
- **Happy path**: 最终总结包含 decision_advice、consensus_points、dissent_points
- **Edge case**: max_rounds=1 时，只进行一轮讨论后直接总结
- **Edge case**: 用户发送 `/stop` → 提前终止，用已有历史总结
- **Error path**: LLM 不可用 → 主持人用已有历史拼接总结
- **Error path**: 某专家发言失败 → 跳过该专家，其他专家继续
- **Error path**: 所有专家发言失败 → 提前进入总结阶段
- **Integration**: `board_started`、`expert_speech`、`round_summary`、`board_concluded` 事件正确广播

**Verification**: `pytest tests/unit/experts/test_board_orchestrator.py` 通过

---

### U6. 后端集成 BoardRouter 到主聊天流程

**Goal**: 在 `chat.py` 的 WebSocket 处理中接入 `BoardRouter`，实现 `@board` 前缀触发私董会讨论，并通过 `emit_team_event()` 推送事件到前端。

**Requirements**: FR-1, FR-10, FR-11, FR-15

**Dependencies**: U3, U5

**Files**:
- `src/agentkit/server/routes/chat.py` — 修改 `_handle_chat_message`，接入 `BoardRouter`
- `src/agentkit/server/app.py` — 启动时加载 `configs/experts/`，挂载 `expert_template_registry` 和 `board_config` 到 `app.state`
- `src/agentkit/server/config.py` — 新增 `board` 配置项（max_rounds、default_template、parallel_speech、history_compression_threshold）
- `tests/unit/server/test_chat_board_integration.py` — 新建

**Approach**:
- 在 `app.py` 启动时（参考 skills 加载逻辑 `app.py:261-282`）：
  - 创建 `ExpertTemplateRegistry` 实例
  - 调用 `load_from_directory("configs/experts/")` 加载所有专家 YAML
  - 挂载到 `app.state.expert_template_registry`
  - 从 `agentkit.yaml` 读取 `board` 配置，挂载到 `app.state.board_config`
- 在 `chat.py` 的 `_handle_chat_message` 中：
  - 在 `RequestPreprocessor` 之前，检查 `@board` 前缀
  - 如果匹配 `@board`，创建 `BoardRouter`，解析路由
  - 创建 `BoardTeam` 和 `BoardOrchestrator`
  - 注册 `handoff_transport` 的 handler，将事件转发到 WebSocket（调用 `emit_team_event()`）
  - 调用 `orchestrator.execute(topic)`
  - 将最终结果作为 `final_answer` 发送
- 扩展 `_VALID_TEAM_EVENT_TYPES`：新增 `board_started`、`expert_speech`、`round_summary`、`user_intervention`、`board_concluded`
- 用户干预处理：讨论进行中，如果用户发送新消息（非 `/stop`），通过 `board_team.broadcast_user_message()` 广播

**Patterns to follow**: 
- skills 加载模式：`src/agentkit/server/app.py:261-282`
- `emit_team_event()` 辅助函数：`src/agentkit/server/routes/chat.py:117-142`

**Test scenarios**:
- **Happy path**: `@board:elon_musk,jeff_bezos 讨论主题` → 触发 BoardRouter，创建 BoardTeam，执行讨论
- **Happy path**: 讨论事件通过 `emit_team_event()` 推送到 WebSocket
- **Happy path**: `@board 讨论主题` → 使用默认 private_board 模板
- **Edge case**: 讨论中用户发送消息 → 广播为 user_intervention
- **Edge case**: 讨论中用户发送 `/stop` → 终止讨论
- **Integration**: `app.state.expert_template_registry` 在启动时正确加载
- **Integration**: `@board` 与 `@team` 和普通聊天互不干扰

**Verification**: `pytest tests/unit/server/test_chat_board_integration.py` 通过；手动测试 `@board` 触发讨论

---

### U7. 前端事件类型和处理扩展

**Goal**: 在前端 TypeScript 类型和 Pinia store 中新增私董会事件类型和处理逻辑。

**Requirements**: FR-10, FR-12, FR-13

**Dependencies**: U6

**Files**:
- `src/agentkit/server/frontend/src/api/types.ts` — 新增 board 事件类型和接口
- `src/agentkit/server/frontend/src/stores/chat.ts` — 新增 board 事件处理
- `src/agentkit/server/frontend/src/stores/team.ts` — 新增 board 状态管理（可选，或新建 `stores/board.ts`）

**Approach**:
- 在 `types.ts` 中：
  - 新增 `WsServerMessage` 联合类型成员：`board_started`、`expert_speech`、`round_summary`、`user_intervention`、`board_concluded`
  - 新增 `IBoardState` 接口：`team_id`、`topic`、`experts`、`moderator_name`、`current_round`、`max_rounds`、`status`
  - 新增 `IBoardSpeech` 接口：`expert_name`、`expert_avatar`、`expert_color`、`content`、`round`、`role`
- 在 `chat.ts` 的 `handleWsMessage` 中新增 case：
  - `board_started`: 创建 board 状态，推送步骤提示
  - `expert_speech`: 创建专家消息（带头像、颜色、轮次标识），追加到消息列表
  - `round_summary`: 创建主持人小结消息（特殊样式，message_type='milestone'）
  - `user_intervention`: 标记用户消息已广播
  - `board_concluded`: 创建总结消息（含决策建议、共识点、分歧点）
- 参考 `chat.ts:554-646` 的现有 team 事件处理模式

**Patterns to follow**: `src/agentkit/server/frontend/src/stores/chat.ts:554-646` 的 team 事件处理

**Test scenarios**:
- **Test expectation**: none — 前端 TypeScript 类型，由 U8 的组件测试和手动测试覆盖

**Verification**: `npm run typecheck` 通过

---

### U8. 前端群聊式 UI 增强

**Goal**: 增强 `ExpertMessage.vue` 组件，新增讨论状态展示，实现群聊式体验。

**Requirements**: FR-12, FR-13, FR-14

**Dependencies**: U7

**Files**:
- `src/agentkit/server/frontend/src/components/chat/ExpertMessage.vue` — 增强（新增轮次标识、角色标签）
- `src/agentkit/server/frontend/src/components/chat/BoardStatusView.vue` — 新建（讨论状态展示）
- `src/agentkit/server/frontend/src/views/ChatView.vue` — 集成 BoardStatusView

**Approach**:
- 增强 `ExpertMessage.vue`：
  - 新增 props：`round?: number`、`role?: 'expert' | 'moderator' | 'user'`
  - 显示轮次标识（如"第 2 轮"）
  - 主持人消息特殊样式（背景色、边框）
  - 用户干预消息右侧气泡展示
- 新建 `BoardStatusView.vue`：
  - 顶部显示：讨论主题、当前轮次/最大轮次、参与专家列表（头像、名称、角色标签）
  - 专家列表可点击查看其所有发言
  - 讨论结束后展示总结卡片（决策建议、共识点、分歧点）
- 在 `ChatView.vue` 中：
  - 当 board 状态激活时，渲染 `<BoardStatusView />`（类似现有 `<ExpertTeamView />`）

**Patterns to follow**: 
- `src/agentkit/server/frontend/src/components/chat/ExpertMessage.vue` 现有组件
- `src/agentkit/server/frontend/src/components/chat/ExpertTeamView.vue` 团队视图
- `src/agentkit/server/frontend/src/views/ChatView.vue:19` 的 ExpertTeamView 集成

**Test scenarios**:
- **Test expectation**: none — Vue 组件，由手动测试覆盖

**Verification**: `npm run typecheck` 通过；手动测试 `@board` 触发讨论，前端正确展示群聊

---

### U9. 单元测试覆盖

**Goal**: 为所有新增模块编写单元测试，确保覆盖率 ≥ 80%。

**Requirements**: 成功标准 §7.1

**Dependencies**: U1-U8

**Files**:
- `tests/unit/experts/test_config.py` — 扩展（U1 新字段测试）
- `tests/unit/experts/test_board_router.py` — 新建（U3）
- `tests/unit/experts/test_board.py` — 新建（U4）
- `tests/unit/experts/test_board_orchestrator.py` — 新建（U5）
- `tests/unit/server/test_chat_board_integration.py` — 新建（U6）

**Approach**:
- 使用 `pytest` + `pytest-asyncio`（asyncio_mode=auto）
- Mock `LLMGateway`、`AgentPool`、`HandoffTransport` 进行隔离测试
- 测试覆盖：
  - 配置字段序列化/反序列化
  - 路由解析各种格式
  - BoardTeam 生命周期和状态转换
  - BoardOrchestrator 讨论流程（正常、异常、用户干预）
  - chat.py 集成（@board 触发、事件广播）
- 测试标记：单元测试无特殊标记，集成测试标记 `@pytest.mark.integration`

**Patterns to follow**: 
- `tests/unit/experts/test_team_orchestrator.py` 的测试模式
- `tests/unit/experts/test_router.py` 的路由测试模式

**Test scenarios**:
- 见各实现单元的测试场景

**Verification**: `pytest tests/unit/experts/ tests/unit/server/test_chat_board_integration.py -v` 全部通过；`pytest --cov=src/agentkit/experts --cov-report=term-missing` 覆盖率 ≥ 80%

---

## Risks & Dependencies

### Risks

| 风险 | 影响 | 缓解 |
|------|------|------|
| 专家发言同质化 | 讨论质量低 | 强化角色 prompt 差异化，`decision_framework` 字段强制不同视角 |
| token 消耗过高（5轮×5专家=25次调用） | 成本问题 | 提供轮次配置，历史压缩机制 |
| 讨论发散无结论 | 用户体验差 | 主持人每轮小结，最终强制总结 |
| 名人 persona 不准确 | 发言不像本人 | YAML 可迭代优化，未来支持蒸馏 |
| `chat.py` 集成复杂度高 | 可能破坏现有聊天 | `@board` 路由在 `RequestPreprocessor` 之前检查，不影响普通聊天 |
| 前端事件处理与现有 team 事件冲突 | UI 错乱 | 事件类型独立（board_* vs team_*），store 独立 |

### Dependencies

- **现有基础设施**: `Expert`、`AgentPool`、`HandoffTransport`、`SharedWorkspace`、`ExpertTemplateRegistry`
- **LLM Gateway**: `src/agentkit/llm/gateway.py` 提供多 provider 支持
- **WebSocket**: `src/agentkit/server/routes/chat.py` 现有 WebSocket 通道
- **前端组件**: `ExpertMessage.vue`、`ChatView.vue`、`stores/chat.ts`

---

## System-Wide Impact

### 影响方

- **终端用户**: 获得私董会讨论能力，可就决策类问题获得多视角建议
- **开发者**: 新增 `@board` 路由模式，需了解与 `@team` 的区别
- **配置管理**: 新增 `configs/experts/` 目录和 `agentkit.yaml` 的 `board` 配置项
- **前端**: 新增 board 事件处理和 UI 组件

### 兼容性

- `ExpertConfig` 新增字段有默认值，向后兼容
- `@board` 路由独立，不影响 `@team` 和普通聊天
- `_VALID_TEAM_EVENT_TYPES` 扩展是增量式，不影响现有事件
- 前端事件处理新增 case，不影响现有 case

---

## Open Questions

1. **历史压缩 prompt 具体设计** — 超过 token 阈值时，主持人如何压缩历史？
   - **决策**: 实现时细化，初步思路是让主持人总结每轮关键观点，替换原始发言。

2. **用户干预消息的实时性** — 用户发送干预后，当前轮次是否立即中断？
   - **决策**: 不中断当前轮次，干预消息在下一轮生效。避免复杂的中断逻辑。

3. **private_board 模板格式** — 如何在 YAML 中定义"团队模板"（引用多个专家）？
   - **决策**: `private_board.yaml` 使用 `members: [expert1, expert2, ...]` 字段，`BoardRouter` 解析时加载成员配置。

4. **讨论历史持久化** — 讨论结束后是否保存到数据库？
   - **决策**: 本期不持久化，仅保存到 SharedWorkspace。未来可扩展。

---

## Sources & Research

- **需求文档**: `docs/brainstorms/2026-06-17-board-meeting-mode-requirements.md`
- **现有实现**: `src/agentkit/experts/` 目录所有文件
- **对标产品**: Qoder Experts Mode、WorkBuddy、Legends MCP、colleague.skill（详见需求文档 §1.2）
- **架构参考**: AgentVerse 通信框架、ARMOR-MAD 协议阈值终止

---

**Next Step**: 交由 `/ce-work` 执行实现，或由开发者按 U1-U9 顺序逐步实现。
