type: user

role: user

content:
审查以下设计规范文档的质量、完整性和一致性：

文件路径: /root/projects/qq-shell/docs/superpowers/specs/2026-04-07-butler-shell-design.md

审查要点：
1. **完整性** - 是否覆盖了所有必要的设计方面（架构、数据模型、API、错误处理、测试）
2. **一致性** - 各部分之间是否有矛盾或不一致的地方
3. **清晰度** - 是否足够清晰，能让实施者理解要构建什么
4. **可行性** - 设计是否可实现，是否有明显的技术障碍
5. **安全考虑** - 是否有安全漏洞或风险未考虑
6. **扩展性** - 是否有足够的扩展点

请提供具体的改进建议，标注问题位置和修改方案。

userType: external

entrypoint: cli

gitBranch: HEAD

slug: recursive-knitting-river


type: message

role: assistant

type: thinking

thinking:
用户要求我审查一个设计规范文档的质量、完整性和一致性。我需要先读取这个文件，然后根据用户提供的审查要点进行详细分析。

让我先读取这个文件。

type: assistant


service_tier: standard

speed: standard


content:
1	---
2	name: Butler-Shell 系统设计
3	description: 基于 Inngest 与 tmux 的持久化 Shell 助手 (QQ 桥接)
4	type: project
5	---
6
7	# Butler-Shell 系统设计
8
9	## 概述
10
11	Butler-Shell 是一个通过 QQ 接收指令、在远程服务器上维护持久化 Shell 会话的系统。核心特性：
12
13	- **双模式切换**：自动在自然语言模式与 PTY 透传交互模式间切换
14	- **命令准入**：危险命令需要用户审批
15	- **上下文压缩**：`/compact` 指令压缩会话上下文
16	- **可扩展 Skills**：插件化功能扩展
17
18	## 技术栈
19
20	| 组件 | 技术选型 |
21	|------|----------|
22	| 任务编排 | Inngest (Python SDK) + 自托管 Server |
23	| PTY 容器 | tmux |
24	| QQ 接入 | NapCatQQ (WebSocket) |
25	| 状态存储 | Inngest State |
26	| 日志存储 | SQLite |
27	| Agent Logic | Claude API |
28
29	## 架构
30
31	```
32	┌─────────────────────────────────────────────────────────┐
33	│                    QQ Gateway                           │
34	│              (NapCatQQ WebSocket Handler)               │
35	└─────────────────────┬───────────────────────────────────┘
36	                      │ 消息事件
37	┌─────────────────────▼───────────────────────────────────┐
38	│                 Inngest Functions                       │
39	│  ┌─────────────┐ ┌─────────────┐ ┌─────────────┐       │
40	│  │handle_msg   │ │guardrail    │ │compaction   │       │
41	│  └─────────────┘ └─────────────┘ └─────────────┘       │
42	└─────────────────────┬───────────────────────────────────┘
43	                      │ 状态管理
44	┌─────────────────────▼───────────────────────────────────┐
45	│              Session Manager (TmuxWrapper)              │
46	│  ┌──────────────┐ ┌──────────────┐ ┌──────────────┐    │
47	│  │create_session│ │capture_pane │ │detect_mode   │    │
48	│  └──────────────┘ └──────────────┘ └──────────────┘    │
49	└─────────────────────┬───────────────────────────────────┘
50	                      │ PTY 控制
51	┌─────────────────────▼───────────────────────────────────┐
52	│                    tmux sessions                        │
53	│              [user_001] [user_002] ...                  │
54	└─────────────────────────────────────────────────────────┘
55	```
56
57	## 项目结构
58
59	```
60	butler-shell/
61	├── src/
62	│   └── butler/
63	│       ├── __init__.py
64	│       ├── main.py                    # FastAPI 入口 + Inngest Serve
65	│       │
66	│       ├── gateway/                   # QQ 消息接入层
67	│       │   ├── __init__.py
68	│       │   ├── napcat.py              # NapCatQQ WebSocket 客户端
69	│       │   └── events.py              # 消息事件定义
70	│       │
71	│       ├── workflows/                 # Inngest 工作流
72	│       │   ├── __init__.py
73	│       │   ├── handle_message.py      # 主消息处理流
74	│       │   ├── guardrail.py           # 命令准入审批
75	│       │   └── compaction.py          # 上下文压缩
76	│       │
77	│       ├── session/                   # Tmux 会话管理
78	│       │   ├── __init__.py
79	│       │   ├── wrapper.py             # TmuxWrapper 核心类
80	│       │   ├── detector.py            # 模式检测器
81	│       │   └── state.py               # 会话状态模型
82	│       │
83	│       ├── skills/                    # Skill 扩展系统
84	│       │   ├── __init__.py
85	│       │   ├── base.py                # SkillManager 基类
86	│       │   ├── log_skill.py           # 日志记录 Skill
87	│       │   └── system_skill.py        # 系统信息 Skill
88	│       │
89	│       └── config.py                  # 配置管理
90	│
91	├── tests/
92	│   ├── conftest.py
93	│   ├── test_wrapper.py
94	│   ├── test_detector.py
95	│   └── test_workflows.py
96	│
97	├── docs/
98	│   └── specs/
99	│
100	├── pyproject.toml
101	├── requirements.txt
102	└── docker-compose.yml                 # Inngest Server + 依赖
103	```
104
105	## 核心数据模型
106
107	### SessionState
108
109	```python
110	from enum import Enum
111	from pydantic import BaseModel, Field
112	from datetime import datetime
113	from typing import Optional
114
115	class SessionMode(str, Enum):
116	    """会话运行模式"""
117	    NATURAL_LANGUAGE = "nl"      # 自然语言模式 - 通过 LLM 解析
118	    INTERACTIVE = "interactive"  # 交互模式 - 直接透传到 PTY
119
120	class SessionState(BaseModel):
121	    """会话状态快照"""
122	    session_id: str = Field(..., description="tmux session 名称")
123	    user_id: str = Field(..., description="QQ 用户 ID")
124	    mode: SessionMode = Field(default=SessionMode.NATURAL_LANGUAGE)
125
126	    # Shell 状态
127	    pwd: str = Field(default="", description="当前工作目录")
128	    env: dict[str, str] = Field(default_factory=dict, description="关键环境变量")
129	    last_output: str = Field(default="", description="最近终端输出摘要")
130
131	    # 交互模式追踪
132	    interactive_process: Optional[str] = Field(
133	        default=None,
134	        description="当前交互进程名 (vim, top, etc.)"
135	    )
136
137	    # 元数据
138	    created_at: datetime = Field(default_factory=datetime.utcnow)
139	    updated_at: datetime = Field(default_factory=datetime.utcnow)
140	```
141
142	### MessageContext
143
144	```python
145	class MessageContext(BaseModel):
146	    """消息处理上下文"""
147	    message_id: str
148	    user_id: str
149	    content: str
150	    is_command: bool = False          # 是否以 / 开头
151	    requires_approval: bool = False   # 危险命令标记
152	    session: Optional[SessionState] = None
153	```
154
155	## TmuxWrapper 核心 API
156
157	```python
158	class TmuxWrapper:
159	    """tmux 会话封装器"""
160
161	    # 交互模式进程名单
162	    INTERACTIVE_PROCESSES = frozenset([
163	        "vim", "nvim", "vi",
164	        "top", "htop", "btop",
165	        "less", "more", "man",
166	        "claude", "aider",
167	        "python", "node", "irb", "ipython",
168	    ])
169
170	    # 快捷键映射
171	    SPECIAL_KEYS = {
172	        "C-c", "C-d", "C-z", "C-a", "C-e",
173	        "Esc", "Tab", "Up", "Down", "Left", "Right",
174	        "Enter", "Space",
175	    }
176
177	    def create_session(self, user_id: str) -> str:
178	        """为用户创建独立 tmux session"""
179
180	    def session_exists(self, session_name: str) -> bool:
181	        """检查 session 是否存在"""
182
183	    def kill_session(self, session_name: str) -> None:
184	        """销毁 session"""
185
186	    def send_keys(self, session_name: str, keys: str, enter: bool = True) -> None:
187	        """向 session 发送按键"""
188
189	    def send_raw(self, session_name: str, data: str) -> None:
190	        """发送原始数据（交互模式精确控制）"""
191
192	    def capture_pane(self, session_name: str, as_ansi: bool = False) -> str:
193	        """抓取终端屏幕内容"""
194
195	    def get_active_process(self, session_name: str) -> Optional[str]:
196	        """获取 tmux 窗口中的活跃进程名"""
197
198	    def get_pty_state(self, session_name: str) -> PtyState:
199	        """检测 PTY 是否在等待输入（通过 /proc 状态监控）"""
200
201	    def detect_mode(self, session_name: str) -> SessionMode:
202	        """混合模式检测：进程名单匹配 + PTY 状态检测"""
203	```
204
205	## Inngest 工作流
206
207	### handle_im_message
208
209	```
210	Step 1: get-or-create-session → butler_<user_id>
211	Step 2: load-state → SessionState
212	Step 3: detect-mode → NATURAL_LANGUAGE | INTERACTIVE
213
214	INTERACTIVE 模式:
215	  └─ send_keys(content, enter=False) → capture_pane() → 返回快照
216
217	NATURAL_LANGUAGE 模式:
218	  ├─ Skill 匹配? → execute Skill → 返回结果
219	  ├─ 危险命令? → 发送 im/command-needs-approval 事件
220	  ├─ 特殊指令? → 执行对应逻辑
221	  └─ send_keys(content, enter=True) → capture_pane() → 返回输出
222	```
223
224	### command_guardrail
225
226	```
227	Step 1: send-confirmation-request → 发送确认请求到 QQ
228	Step 2: wait-approval → ctx.step.wait_for_event (最长 5 分钟)
229	Step 3: 处理用户回复 → 执行或取消
230	```
231
232	### context_compaction
233
234	```
235	Step 1: get-pwd → 获取当前工作目录
236	Step 2: get-env → 获取关键环境变量
237	Step 3: get-output → 抓取最近终端输出
238	Step 4: summarize → LLM 总结（可选）
239	Step 5: 更新状态快照 → ctx.state.set()
240	```
241
242	## 消息处理流程
243
244	```
245	QQ 消息到达
246	     │
247	     ▼
248	NapCatGateway ──→ 转换为 NapCatEvent
249	     │
250	     ▼
251	Inngest Event ──→ 发送 im/message 事件
252	     │
253	     ▼
254	handle_im_message workflow
255	     │
256	     ├─ INTERACTIVE 模式 ──→ send_keys + capture_pane
257	     │
258	     └─ NATURAL_LANGUAGE 模式
259	          ├─ Skill 匹配 ──→ execute Skill
260	          ├─ 危险命令 ──→ command_guardrail
261	          └─ 正常命令 ──→ execute + capture
262	     │
263	     ▼
264	NapCatGateway ──→ 发送 QQ 回复
265	```
266
267	## 危险命令检测
268
269	扩展集合，包括：
270
271	| 命令模式 | 说明 |
272	|----------|------|
273	| `rm -rf` | 递归强制删除 |
274	| `chmod 777` | 开放所有权限 |
275	| `chown` | 修改所有者 |
276	| `dd` | 磁盘操作 |
277	| `mkfs` | 格式化 |
278	| `fdisk`/`parted` | 分区操作 |
279	| `> /dev/sd*` | 写入磁盘设备 |
280	| `iptables` | 防火墙规则 |
281	| `shutdown`/`reboot` | 系统关机/重启 |
282
283	## Skill 扩展系统
284
285	### 基类 API
286
287	```python
288	class SkillBase(ABC):
289	    name: str
290	    description: str
291	    triggers: list[str]
292
293	    @abstractmethod
294	    async def execute(self, ctx: SkillContext) -> SkillResult:
295	        pass
296
297	    def matches(self, content: str) -> bool:
298	        """检查是否匹配触发条件"""
299	```
300
301	### 内置 Skills
302
303	| Skill | 触发器 | 功能 |
304	|-------|--------|------|
305	| LogSkill | `/log`, `/history` | 记录和检索 Shell 交互日志 |
306	| SystemSkill | `/sys`, `/system`, `/load` | 获取系统负载和资源信息 |
307
308	## 错误处理
309
310	### 错误分类
311
312	| 类型 | 说明 | 处理方式 |
313	|------|------|----------|
314	| TRANSIENT | 暂时性错误 | Inngest 自动重试 |
315	| PERMANENT | 永久性错误 | 返回用户友好消息 |
316	| USER_ERROR | 用户输入错误 | 提示正确用法 |
317
318	### 关键错误类型
319
320	- `SessionNotFoundError`: 会话不存在（可恢复）
321	- `TmuxCommandError`: tmux 命令执行失败（可恢复）
322	- `ApprovalTimeoutError`: 审批超时
323
324	## 测试策略
325
326	| 层级 | 测试类型 | 覆盖目标 |
327	|------|----------|----------|
328	| TmuxWrapper | 单元测试 | 100% 方法覆盖 |
329	| 模式检测 | 单元测试 | 所有进程类型 |
330	| 工作流 | 集成测试 | 主路径 + 错误路径 |
331	| Skill | 单元测试 | 所有触发场景 |
332	| 端到端 | E2E 测试 | 完整消息流程 |
333
334	## 部署配置
335
336	### docker-compose.yml
337
338	```yaml
339	version: '3.8'
340	services:
341	  inngest:
342	    image: inngest/inngest:latest
343	    ports:
344	      - "8288:8288"
345	    command: start --url http://host.docker.internal:8000/api/inngest
346	    extra_hosts:
347	      - "host.docker.internal:host-gateway"
348
349	  napcat:
350	    image: mlikiowa/napcat-docker:latest
351	    ports:
352	      - "3001:3001"
353	    volumes:
354	      - ./napcat-data:/app/napcat/config
355	```
356
357	### 环境变量
358
359	```bash
360	INNGEST_EVENT_KEY=your_event_key
361	INNGEST_SIGNING_KEY=your_signing_key
362	NAPCAT_WS_URL=ws://localhost:3001
363	NAPCAT_TOKEN=your_napcat_token
364	ANTHROPIC_API_KEY=your_claude_api_key
365	```
366
367	## 实施计划
368
369	按以下顺序实施：
370
371	1. **Phase 1: 核心会话层**
372	   - TmuxWrapper 实现
373	   - 模式检测器实现
374	   - 单元测试
375
376	2. **Phase 2: Inngest 工作流**
377	   - handle_message 工作流
378	   - guardrail 审批流程
379	   - 集成测试
380
381	3. **Phase 3: QQ Gateway**
382	   - NapCatQQ 集成
383	   - 消息转换
384	   - 端到端测试
385
386	4. **Phase 4: Skills 系统**
387	   - Skill 基类
388	   - LogSkill 实现
389	   - SystemSkill 实现
390
391	5. **Phase 5: 完善**
392	   - 上下文压缩
393	   - 错误处理优化
394	   - Mock 测试脚本
395
[result-id: r1]


thinking:
用户要求我审查设计规范文档的质量、完整性和一致性。让我仔细分析这个文档，并从以下六个方面进行评估：

1. 完整性 - 是否覆盖了所有必要的设计方面
2. 一致性 - 各部分之间是否有矛盾
3. 清晰度 - 是否足够清晰
4. 可行性 - 设计是否可实现
5. 安全考虑 - 是否有安全漏洞
6. 扩展性 - 是否有足够的扩展点

让我逐一分析：

## 1. 完整性分析

文档覆盖的方面：
- 架构设计 ✓
- 数据模型 ✓
- API 设计 ✓
- 工作流 ✓
- 错误处理 ✓
- 测试策略 ✓
- 部署配置 ✓
- 实施计划 ✓

缺失或不完整的部分：
- **安全考虑**: 没有专门的安全章节，只是简单提到了危险命令检测，缺少：
  - 认证/授权机制
  - 敏感数据处理（API keys、token）
  - 会话隔离的安全性
  - 输入验证
  - 日志敏感信息过滤
  - QQ 消息验证机制（防止伪造消息）

- **性能考虑**: 没有性能相关的设计
  - 并发会话数量限制
  - 消息队列处理能力
  - tmux 会话资源消耗
  - 长时间运行的会话清理

- **可观测性**: 缺少
  - 日志格式和级别
  - 监控指标
  - 告警机制
  - 健康检查端点

- **配置管理**:
  - 缺少配置热更新机制
  - 没有配置验证

- **数据持久化细节**:
  - SQLite 日志存储的 schema 未定义
  - 没有数据库迁移策略
  - 没有备份策略

## 2. 一致性分析

发现的不一致之处：
1. 第45行显示 Session Manager 有 `detect_mode` 方法，但第202行 TmuxWrapper 也有 `detect_mode` 方法 - 需要澄清是哪个组件负责模式检测
2. 第26行显示状态存储是 "Inngest State"，但第27行又说 "日志存储 | SQLite" - 状态存储和日志存储是分开的吗？
3. 第106-140行 SessionState 的定义，但 MessageContext 里的 session 字段是 Optional，需要说明什么情况下为 None
4. 危险命令检测列表（第269-282行）中缺少一些危险命令，如 `:(){ :|:& };:` (fork bomb)、`curl | bash` 等

## 3. 清晰度分析

需要改进的地方：
1. 双模式切换的具体逻辑不够清晰：
   - 什么条件下从 NATURAL_LANGUAGE 切换到 INTERACTIVE？
   - 什么条件下从 INTERACTIVE 切换回 NATURAL_LANGUAGE？
   - 用户是否可以手动切换？如何切换？

2. Skill 系统的触发机制：
   - "Skill 匹配?" 的匹配逻辑是什么？
   - 触发器是前缀匹配还是正则表达式？

3. 模式检测的具体实现：
   - `get_pty_state` 返回什么？
   - PtyState 的定义缺失

4. 消息格式：
   - QQ 消息的格式是什么？
   - 支持哪些消息类型（文本、图片、文件）？

## 4. 可行性分析

潜在技术障碍：
1. **模式检测可靠性**: 依赖进程名和 PTY 状态检测可能不可靠
   - 某些程序可能 fork 子进程
   - 某些程序可能在后台运行

2. **tmux 会话隔离**: 多用户场景下的资源隔离
   - 需要考虑用户权限问题
   - 需要防止用户之间的会话干扰

3. **Inngest Python SDK 成熟度**:
   - 需要确认 SDK 功能是否满足需求
   - 需要确认自托管 Inngest Server 的稳定性

4. **NapCatQQ 依赖**:
   - NapCatQQ 是第三方实现，稳定性如何？
   - 有没有备选方案？

5. **审批超时处理**:
   - 5 分钟超时后命令如何处理？
   - 是否需要持久化待审批命令？

## 5. 安全考虑

重大安全风险：
1. **认证缺失**: 没有说明如何验证消息来源
   - 任何人知道 QQ 机器人账号都能发送命令？
   - 有没有白名单机制？

2. **命令注入风险**:
   - `send_keys` 是否有输入验证？
   - 特殊字符如何处理？

3. **敏感信息泄露**:
   - 终端输出可能包含密码、token
   - 日志存储如何处理敏感信息？

4. **会话劫持**:
   - session_id 生成规则？
   - 防止用户冒充？

5. **危险命令检测不足**:
   - 用户可以用 `sudo rm -rf` 绕过
   - 可以用 `sh -c 'rm -rf /'` 绕过
   - 需要更智能的检测机制

## 6. 扩展性分析

扩展性设计：
1. **Skill 系统设计良好**: 基类抽象清晰，易于扩展
2. **缺少以下扩展点**:
   - 中间件机制（用于认证、日志、限流等）
   - 插件配置管理
   - 动态加载机制
   - 版本管理

---

让我整理成一份完整的审查报告。


type: text

text:
我已经仔细阅读了这份设计规范文档。以下是我的详细审查结果：

---

## 设计规范文档审查报告

**文件**: `/root/projects/qq-shell/docs/superpowers/specs/2026-04-07-butler-shell-design.md`

---

### 一、优点概述

文档整体结构清晰，技术栈选型合理，项目结构规划得当。以下方面设计良好：
- 数据模型定义清晰
- 工作流设计思路清晰
- Skill 扩展系统设计合理
- 错误分类明确
- 实施计划分阶段可行

---

### 二、Critical Issues (必须修复)

#### 2.1 安全设计严重缺失

文档缺少专门的安全设计章节，存在以下重大风险：

**问题位置**: 整个文档缺少安全章节

**具体问题**:

1. **认证机制缺失**: 没有说明如何验证消息来源的合法性
   - 任何知道机器人 QQ 号的人都能发送命令执行 Shell 指令
   - 缺少用户白名单/黑名单机制

2. **危险命令检测可被绕过** (第269-282行):
   ```
   用户可以通过以下方式绕过检测：
   - sudo rm -rf /  (未检测 sudo)
   - sh -c 'rm -rf /'  (命令嵌套)
   - echo "rm -rf /" | bash  (管道执行)
   - chmod -R 777 /  (递归参数未检测)
   - :(){ :|:& };:  (fork bomb)
   ```

3. **会话隔离安全**:
   - `butler_<user_id>` 命名规则可预测
   - 没有防止会话劫持的机制

**修改建议**:

```markdown
## 安全设计

### 认证与授权

| 机制 | 说明 |
|------|------|
| 用户白名单 | 仅允许配置文件中的 QQ 用户 ID |
| 消息签名验证 | 验证 NapCatQQ 消息来源 |
| 会话令牌 | 每个会话生成唯一令牌，防止劫持 |

### 命令安全检测

危险命令检测应使用 AST 解析而非正则匹配：
- 使用 `shlex.split()` 解析命令
- 检测命令树中的危险操作节点
- 阻止命令嵌套执行

### 敏感信息处理

- 终端输出过滤：移除匹配密码模式的文本
- 日志脱敏：API Key、Token 等不记录明文
```

#### 2.2 模式切换逻辑不完整

**问题位置**: 第13行提到"双模式切换"，但第214-222行工作流只描述了检测后的处理，缺少：

1. **INTERACTIVE 模式何时切换回 NATURAL_LANGUAGE?**
   - 进程退出后自动切换？
   - 用户手动切换？如何操作？
   - 检测失败的降级策略？

**修改建议** (在第214行后添加):

```markdown
### 模式切换规则

| 切换方向 | 触发条件 | 用户可干预 |
|----------|----------|------------|
| NL → INTERACTIVE | 检测到交互进程启动 | 否 |
| INTERACTIVE → NL | 检测到进程退出 | 是，发送 `/nl` |
| INTERACTIVE → NL | 发送 `C-d` 或 `C-c` | 是 |

### 模式检测降级

当模式检测失败时（如 /proc 访问权限问题）：
- 默认使用 NATURAL_LANGUAGE 模式
- 记录告警日志
- 提示用户手动切换
```

---

### 三、Important Issues (应该修复)

#### 3.1 数据模型不完整

**问题位置**: 第198-199行

```python
def get_pty_state(self, session_name: str) -> PtyState:
    """检测 PTY 是否在等待输入（通过 /proc 状态监控）"""
```

**问题**: `PtyState` 类型未定义

**修改建议** (在 SessionState 定义后添加):

```python
class PtyState(str, Enum):
    """PTY 状态"""
    IDLE = "idle"           # 空闲，等待输入
    RUNNING = "running"     # 正在执行命令
    BLOCKED = "blocked"     # 阻塞中（如等待 I/O）
    UNKNOWN = "unknown"     # 状态检测失败
```

#### 3.2 会话生命周期管理缺失

**问题位置**: 整个文档

**问题**: 没有说明会话的生命周期管理：
- 会话何时创建？
- 会话何时销毁？
- 长时间不活跃的会话如何处理？
- 并发会话数量限制？

**修改建议** (添加新章节):

```markdown
## 会话生命周期管理

### 会话策略

| 配置项 | 默认值 | 说明 |
|--------|--------|------|
| SESSION_IDLE_TIMEOUT | 3600s | 空闲超时后自动销毁 |
| MAX_SESSIONS_PER_USER | 1 | 每用户最大会话数 |
| MAX_TOTAL_SESSIONS | 100 | 全局最大会话数 |

### 会话清理

定时任务每小时执行：
1. 扫描所有会话的最后活跃时间
2. 超过 `SESSION_IDLE_TIMEOUT` 的会话标记为待清理
3. 发送通知给用户（可选）
4. 优雅关闭 tmux 会话
```

#### 3.3 一致性问题

**问题位置**: 第45行 vs 第202行

```
第45行：Session Manager (TmuxWrapper) 有 detect_mode
第202行：TmuxWrapper 类有 detect_mode 方法
```

**问题**: 架构图显示 `detect_mode` 在 Session Manager 层，但 API 定义在 TmuxWrapper 类中，需要澄清职责边界。

**修改建议**: 明确说明 TmuxWrapper 是 Session Manager 的核心实现类，或调整架构图。

#### 3.4 SQLite 日志存储 Schema 未定义

**问题位置**: 第26行提到 "日志存储 | SQLite"

**问题**: 没有定义数据库表结构

**修改建议** (添加):

```markdown
### 日志存储 Schema

```sql
CREATE TABLE shell_logs (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    session_id TEXT NOT NULL,
    user_id TEXT NOT NULL,
    command TEXT NOT NULL,
    output TEXT,
    executed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    approved BOOLEAN DEFAULT TRUE,
    approval_id TEXT
);

CREATE INDEX idx_session_logs ON shell_logs(session_id);
CREATE INDEX idx_user_logs ON shell_logs(user_id);
```
```

#### 3.5 错误处理缺少具体策略

**问题位置**: 第308-323行

**问题**: 错误分类表只列出了类型，缺少：
- 具体哪些错误属于哪种类型
- 重试策略（最大重试次数、退避算法）
- 用户友好消息模板

**修改建议**:

```markdown
### 错误分类详情

| 错误类型 | 具体错误 | 分类 | 处理策略 |
|----------|----------|------|----------|
| tmux session 不存在 | SessionNotFoundError | TRANSIENT | 自动重建 session |
| tmux 命令超时 | TmuxTimeoutError | TRANSIENT | 重试 3 次，指数退避 |
| NapCat 连接断开 | GatewayDisconnectedError | TRANSIENT | 重连 + 重试 |
| 用户无权限 | UnauthorizedError | PERMANENT | 直接返回错误消息 |
| 命令被拒绝 | CommandRejectedError | PERMANENT | 记录日志，通知用户 |

### 重试策略

```python
RETRY_CONFIG = {
    "max_retries": 3,
    "initial_delay": 1,  # 秒
    "max_delay": 30,
    "multiplier": 2,
}
```
```

---

### 四、Suggestions (建议改进)

#### 4.1 可观测性设计

建议添加以下内容：

```markdown
## 可观测性

### 日志级别

| 级别 | 使用场景 |
|------|----------|
| DEBUG | 详细执行流程 |
| INFO | 会话创建/销毁、命令执行 |
| WARN | 模式检测失败、降级操作 |
| ERROR | 命令执行失败、外部服务异常 |

### 关键指标

- `butler_sessions_active`: 当前活跃会话数
- `butler_commands_total`: 命令执行总数 (按状态分组)
- `butler_command_duration_seconds`: 命令执行耗时
- `butler_mode_switches_total`: 模式切换次数

### 健康检查端点

- `GET /health`: 服务状态
- `GET /ready`: 就绪状态（检查 NapCat 连接、tmux 可用性）
```

#### 4.2 消息格式规范

建议添加 QQ 消息格式说明：

```markdown
## 消息格式

### 输入消息

NapCatQQ 消息格式（JSON）：
```json
{
  "time": 1712345678,
  "self_id": 12345678,
  "post_type": "message",
  "message_type": "private",
  "user_id": 87654321,
  "message": "命令内容",
  "raw_message": "命令内容"
}
```

### 输出消息

支持的消息类型：
- 文本消息
- 图片（终端截图，可选）
- Markdown 格式（转换为 QQ 富文本）
```

#### 4.3 配置管理

建议添加配置文件结构：

```markdown
## 配置管理

### 配置文件

```yaml
butler:
  session:
    idle_timeout: 3600
    max_per_user: 1

  guardrail:
    enabled: true
    approval_timeout: 300
    danger_patterns:
      - "rm -rf"
      - "sudo"

  users:
    whitelist:
      - "12345678"
      - "87654321"

  logging:
    level: INFO
    path: /var/log/butler/shell.log
```

### 配置热更新

支持运行时重新加载配置：
- `POST /config/reload` 触发重载
- 监听 SIGHUP 信号
```

#### 4.4 Skill 系统完善

**问题位置**: 第283-299行

建议添加：

```markdown
### Skill 注册机制

```python
class SkillRegistry:
    def __init__(self):
        self._skills: dict[str, SkillBase] = {}

    def register(self, skill: SkillBase) -> None:
        """注册 Skill"""
        self._skills[skill.name] = skill

    def match(self, content: str) -> Optional[SkillBase]:
        """根据内容匹配 Skill"""
        for skill in self._skills.values():
            if skill.matches(content):
                return skill
        return None
```

### Skill 动态加载

支持从 `skills/` 目录自动发现并加载 Skill：
- 扫描 `skills/*.py` 文件
- 查找 `SkillBase` 子类
- 自动注册到 SkillRegistry
```

#### 4.5 端到端测试细节

**问题位置**: 第331行

建议添加：

```markdown
### E2E 测试场景

| 场景 | 描述 | 验证点 |
|------|------|--------|
| 新用户首次交互 | 发送消息，创建会话 | 会话创建成功 |
| 正常命令执行 | `ls -la` | 返回正确输出 |
| 危险命令审批 | `rm -rf /tmp/test` | 进入审批流程 |
| 审批超时 | 不响应审批请求 | 5分钟后超时取消 |
| 交互模式切换 | 在 vim 中发送按键 | 正确透传 |
| 模式自动恢复 | 退出 vim | 切换回 NL 模式 |
```

---

### 五、总结

| 类别 | 数量 | 说明 |
|------|------|------|
| Critical | 2 | 安全设计缺失、模式切换逻辑不完整 |
| Important | 5 | 数据模型不完整、生命周期管理缺失、一致性问题、Schema未定义、错误处理策略不具体 |
| Suggestions | 5 | 可观测性、消息格式、配置管理、Skill系统完善、E2E测试细节 |

**整体评价**: 文档框架良好，但安全设计和系统完整性方面需要加强。建议在实施前优先解决 Critical 问题，并在 Phase 1 开始前完善 Important 问题。