# 运行时可观测性

为炼境建立运行时诊断层。当 Claude 需要排查功能状态时，可以通过 MCP 工具直接拿到结构化的真实数据，而不是靠读代码推断。

## 设计思路

```
运行时事件（启动/注入/调用/报错）
        ↓
  SQLite runtime_logs 表（持久化）
        ↓
  MCP get_diagnostics 工具（Claude 可调用）
        ↓
  Claude 得到结构化诊断数据 → 精准定位问题
```

同时修复两个已知的 UI 盲点：
- 设置页 MCP 状态硬编码为"运行中"，不反映真实端口状态
- 产品组成员注入失败时前端无感知，toast 始终显示成功

## 任务卡

### ✅ T1 · SQLite runtime_logs 表
- status: done
- complexity: S
- files: src-tauri/src/db.rs, src-tauri/src/lib.rs
- acceptance:
  - db.rs 新增 runtime_logs 表：`(id, ts TEXT, category TEXT, level TEXT, message TEXT, context TEXT)`
  - 提供全局 `log_event(category, level, message, context_json)` 函数，内部 get pool 写入
  - 表保留最近 500 条（写入时超出自动删除最旧的）
  - db::init() 中建表（IF NOT EXISTS）

### ✅ T2 · 替换 eprintln! 为结构化日志
- status: done
- complexity: S
- files: src-tauri/src/mcp_server.rs, src-tauri/src/mcp_inject.rs, src-tauri/src/commands/groups.rs
- depends: T1
- acceptance:
  - mcp_server.rs：端口绑定成功/失败 → log_event("mcp_server", "info"/"error", ...)
  - mcp_inject.rs：inject/remove 成功/失败 → log_event("mcp_inject", "info"/"error", context 含 project_id + group_id)
  - commands/groups.rs：add_group_member 注入失败 → log_event("mcp_inject", "warn", ...)
  - 保留 eprintln! 作为备份输出，log_event 写入失败时不 panic

### ✅ T3 · MCP Server 新增 get_diagnostics 工具
- status: done
- complexity: M
- files: src-tauri/src/mcp_server.rs
- depends: T1, T2
- acceptance:
  - tools/list 新增 `get_diagnostics` 工具，无必填参数
  - 返回结构：
    - `server`：端口号、进程启动时间（从全局 OnceCell 记录）
    - `inject_summary`：从 runtime_logs 聚合每个 project_id 最后一次注入的 level + message
    - `recent_errors`：最近 20 条 level=error/warn 的日志（ts + category + message）
  - 响应为 Markdown 格式文本，Claude 可直接阅读

### ✅ T4 · 注入失败结果返回前端
- status: done
- complexity: S
- files: src-tauri/src/commands/groups.rs, src/components/manage/ManagePage.tsx
- depends: T2
- acceptance:
  - add_group_member command 返回 `{ ok: bool, inject_warning: Option<String> }`
  - 前端 AddMemberModal：注入成功 → 绿色 toast "成员已添加，MCP 已注入"；inject_warning 有值 → 黄色 toast 显示警告内容
  - 产品组成员卡片：inject 最后一次为 error/warn → 橙色 `⚠ MCP` 徽标替代绿点，hover 显示错误信息

### ✅ T5 · 设置页 MCP 真实健康检查
- status: done
- complexity: S
- files: src-tauri/src/commands/settings.rs, src/lib/commands.ts, src/components/settings/SettingsPage.tsx
- depends: T1
- acceptance:
  - 新增 `check_mcp_health` Tauri command：尝试 HTTP GET `http://localhost:{port}/health`，返回 `{ ok: bool, latency_ms: u64, error: Option<String> }`
  - 设置页 MCP 区块：挂载时自动调用一次，显示真实状态（绿色"运行中 {latency}ms" / 红色"端口未响应: {error}"）
  - 端口保存后自动重新检查

## 决策记录

- runtime_logs 存 SQLite 而非内存，炼境重启后仍可查历史注入记录
- get_diagnostics 返回 Markdown 而非 JSON，Claude 读取更自然，无需额外解析
- T4 只改 add_group_member，remove 失败影响较小（幂等清理），不做 UI 反馈
- 表上限 500 条：足够覆盖数天的操作记录，不会无限膨胀
