---
version: 1.9.0
updated: 2026-07-02
source: dev-manager-tauri
---

# 蓝图更新规则

> ⚠️ 本文件由 dev-manager-tauri 统一管理，请勿手动修改。规则更新请在 dev-manager-tauri 项目中进行。

本文件定义了 `.blueprint/` 目录的维护规范，供 Claude 在对话中遵循。

## 目录结构

```
.blueprint/
├── manifest.yaml        ← 模块列表、关系、布局坐标
├── CONVENTIONS.md       ← 本文件（Claude 行为规则 + 全局推荐规则库）
├── rules.md             ← 项目私有规则（可选，优先级高于全局规则）
├── usage.json           ← 飞轮外环快照数据（炼境自动写入）
└── modules/
    └── <module-id>.md   ← 每个模块的详情 + 任务卡
```

## 蓝图定位（意图层）

蓝图只记录 git 永远无法自动产生的三类信息：

| 类型 | 内容 | 为什么 git 做不到 |
|------|------|----------------|
| **结构** | 模块列表 + 关系图（dependency/related） | git 只知道文件，不知道模块意图和边界 |
| **意图** | 为什么做 + 验收标准 + 复杂度 + 复盘笔记 | commit 记录"做了什么"，不记录"为什么" |
| **规划** | concept / planned 方向 | 还没有代码，git 里什么都没有 |

**不属于蓝图的**（交给 git 信号，蓝图不手动维护）：
- 任务状态（in_progress / done）→ 从 branch / commit 推断
- 涉及文件（files）→ 从 git diff 读取，蓝图里为可选提示
- 进度数字（progress）→ 从任务卡完成比例自动算
- 更新时间（updated）→ 从 git log 读取

> 蓝图是项目的"架构意图层"，不是任务追踪系统。任务追踪的职责交还给 git。

---

## 何时更新蓝图

| 事件 | 操作 |
|------|------|
| 用户确认了新需求 | 在 manifest.yaml 新增模块，创建 modules/<id>.md |
| **开始执行任务卡（信息1）** | **任务卡前缀改为 🔵，status → in_progress（第一行代码之前）** |
| **完成了功能实现（信息2）** | **任务卡前缀改为 ✅，status → done（验收通过之后）** |
| 拆分了大需求为子任务 | 在 modules/<id>.md 中添加任务卡 |
| 调整了架构方向 | 更新 edges 关系，可能调整 area |
| 放弃了某个方向 | 删除对应模块和文件，或标记 status: abandoned |
| **重构已完成的模块（迭代）** | **manifest.iteration 递增，旧任务卡保留，新建替代任务卡，模块加 `## 迭代记录`** |

## 任务卡复杂度定义

| complexity | 含义 | 判断标准 | 推荐执行模型 |
|-----------|------|--------|------------|
| `S` | Simple | 单文件或机械操作；无需理解现有 pattern；可独立完成 | Haiku |
| `M` | Medium | 跨 2-4 个文件；需理解现有代码风格和上下文；有隐式依赖 | Sonnet |
| `L` | Large/Complex | 系统架构级；**无法直接执行，必须先 `/architect` 设计再 `/splitter` 拆分** | Opus（设计）+ Sonnet（执行） |

### 判断速查

- 改动涉及 3 个以上文件且分属不同功能区域 → 至少 M
- 需要先理解现有代码的内在逻辑或约定才能动手 → 至少 M
- 无法在派发时清晰描述完整实现方案 → L，需先 `/architect`
- 单纯的 SQL 建表、类型文件、配置修改 → S

> **注**：`/auto-execute` 技能会按此定义自动路由模型：S 卡委托 Haiku 子 agent，M 卡由当前 Sonnet 执行，L 卡直接标记 blocked 并提示走 `/architect`。

## 模块状态定义

| 状态 | 含义 | 色标 |
|------|------|------|
| `done` | 已实现并验证 | 🟢 绿色 |
| `in_progress` | 正在开发 | 🔵 蓝色 |
| `planned` | 已规划，需求明确 | 🟡 黄色 |
| `concept` | 构思中，信息不完整 | ⚪ 灰色 |
| `blocked` | 执行受阻，需架构师介入 | 🔴 红色 |
| `abandoned` | 方向已放弃或功能已退役，模块保留作历史记录 | ⚫ 深灰 |

## 任务卡格式

modules/<id>.md 中的每个二级标题（`###`）是一张任务卡：

```markdown
### 📋 任务标题
- status: todo
- complexity: M
- files: src/path/to/file.tsx（可选，规划时填预期路径；实际文件由 git diff 追踪，无需回填）
- depends: other-module-id
- acceptance: 简要描述完成标准
- blocked_reason: （仅 status: blocked 时填写）执行受阻的具体原因
- iteration: 1      # 可选，省略时继承 manifest 顶层 iteration 值
- replaces: 旧任务标题  # 可选，仅重构任务填写，说明本卡替代哪张旧卡

详细说明（可选）。
```

### 状态前缀

| 前缀 | status | 含义 |
|------|--------|------|
| ✅ | done | 已完成（信息1 + 信息2 均已写入） |
| 🔵 | in_progress | 执行中或被中断（只有信息1，等待信息2） |
| 📋 | todo | 可派发（信息充足） |
| 💭 | concept | 构思中 |
| 🔴 | blocked | 执行受阻 |

### 可派发标准（📋）

任务卡同时满足以下条件时标记为 📋：
1. status 为 `todo`
2. 有明确的 `acceptance`（验收标准）
3. complexity 为 `S` 或 `M`

`files` 为可选提示字段，有则帮助 agent 更快定位，无则从 git diff 推断，不作派发门槛。

不满足条件的 todo 任务保持无前缀，说明还需补充信息。

### 💭 concept 卡的极简写法

concept 卡是想法 inbox，**不要求 files / acceptance / complexity**，随想随记：

```markdown
### 💭 ServerManagerPanel 表格和软件块有重复逻辑
- status: concept
```

一行就够。等某次对话中方向变清晰，再补全字段、升格为 📋。
**不要因为"信息不全就不记"而让想法消失**——concept 卡存在的意义就是承接碎片。

## manifest.yaml 规范

### 顶层字段

```yaml
version: 1
name: 项目名称
iteration: 1        # 当前迭代号（默认 1，重构已完成模块时手动递增）
updated: YYYY-MM-DD
```

### 模块字段

```yaml
- id: kebab-case-id        # 唯一标识，同时是 modules/ 下的文件名
  name: 显示名称
  area: frontend            # 所属领域 ID
  status: done              # planned/concept 手动设；in_progress/done 优先从 git 信号推断，人工确认
  progress: 100             # 由任务卡完成比例自动算，无需手填；App 根据 done 卡比例渲染
  position: [x, y]          # React Flow 画布坐标（可选）
```

### 边字段

```yaml
- from: module-a
  to: module-b
  type: dependency          # dependency（实线）/ related（虚线）
```

### 领域字段

```yaml
- id: frontend
  name: 前端
  color: "#3B82F6"          # 节点边框/分组背景色
```

## 进度计算

模块的 progress 由其任务卡的完成比例推算：
- 无任务卡的模块：手动设置 progress
- 有任务卡的模块（单迭代）：`完成数 / 总数 × 100`（取整）
- 有任务卡的模块（多迭代）：**只计当前 iteration 的任务卡**，旧迭代 done 任务不计入分母，避免历史完成率虚高

## 迭代管理

### 何时递增 iteration

**需要递增**（重构已完成的功能）：
- 一个已有 ✅ done 任务卡的模块需要重新设计或重写
- 核心交互/架构方案被替换（不是在原有基础上扩展）

**不需要递增**（正常演进）：
- 在现有模块上添加新功能
- 修复 bug
- 新增模块

### 重构时的操作步骤

1. **manifest.yaml 顶层** `iteration` +1，更新 `updated` 日期
2. **旧任务卡**：保留原位，在卡片末尾加一行注释说明被替代（不改 status、不删除）：
   ```markdown
   ### ✅ 旧功能实现
   - status: done
   - iteration: 1
   ...
   > ⚠️ 已被迭代 2「新功能实现」替代，仅作历史记录。
   ```
3. **新任务卡**：新建替代卡，标注 `iteration` 和 `replaces`：
   ```markdown
   ### 📋 新功能实现
   - status: todo
   - iteration: 2
   - replaces: 旧功能实现
   - complexity: M
   - files: ...
   - acceptance: ...
   ```
4. **模块文件**：追加 `## 迭代记录` 段落（见下方格式）
5. **模块 status**：重置为 `in_progress`，progress 按当前迭代任务卡重新计算

### 迭代记录格式

模块文件末尾追加，每次迭代一条：

```markdown
## 迭代记录

### 迭代 2（YYYY-MM-DD）
- **原因**：React Flow 在 50+ 节点时性能卡顿，重构为虚拟化渲染方案
- **替代**：「React Flow 节点图渲染（迭代1）」→「节点图虚拟化渲染」
- **保留**：迭代1的任务卡作为历史记录，不删除
```

### 梦核如何感知迭代

- usage.json 快照携带 `iteration` 字段（见飞轮外环章节）
- 飞轮数据层按 iteration 分组计算完成率，迭代跳变（如 1→2 后完成率骤降）是正常信号
- 梦核 prompt 会展示「完成率跳变项目」摘要，Opus 据此判断是主动重构还是项目失控

## 决策记录格式

模块文件中可添加 `## 决策记录` 段落，记录架构决策的 WHY：

```markdown
## 决策记录

- 选择阿里云 OSS 而非 GitHub Releases 作为更新源，因为国内用户访问 GitHub 不稳定
- 使用 document-driven 蓝图而非数据库存储，因为 Claude 天然支持文件读写且可版本控制
```

桌面 App 会以琥珀色卡片展示在模块详情面板中。

## 飞轮工作流

Claude 在每次对话中应遵循以下流程：

### 阶段 1：进入对话 — 读取蓝图

```
1. 读取 .blueprint/manifest.yaml     ← 项目全景和当前状态
2. 读取 .blueprint/CONVENTIONS.md    ← 工作流规则 + 全局推荐规则
3. 读取 .blueprint/rules.md          ← 项目私有规则（若存在，合并应用，优先级更高）
```

- 识别哪些模块 in_progress，哪些有可派发任务
- 用简短话语告诉用户当前项目进展（如 "18/22 模块已完成，2 个进行中"）

### 阶段 2：讨论需求 — 同步更新蓝图
| 用户说的 | Claude 应做的 |
|----------|--------------|
| "我想加个 XX 功能" | 确认需求后：manifest 加模块 (status: concept)，创建 modules/<id>.md |
| "XX 功能需要 A、B、C 三步" | 在模块文件中拆分为 3 张任务卡 |
| "这个方案确定了" | 模块 status → planned，补充任务卡的 acceptance（files 可选，有则更准确） |
| "开始做 XX" | 模块 status → in_progress |
| "为什么选这个方案" | 记录到模块的 `## 决策记录` |

### 阶段 3：实现功能 — 两阶段执行锁

任务卡执行遵循**两阶段提交**：开始写第一行代码前加锁（信息1），全部完成后解锁（信息2）。只有信息1没有信息2，说明任务被中断。

```
📋 todo
  ↓ 【信息1：加锁】第一行代码改动之前，先更新任务卡
🔵 in_progress
  ↓ 执行代码改动
  ↓
  ├─ 成功 → 【信息2：解锁】更新任务卡前缀为 ✅ → status: done
  │         所有任务卡完成 → 模块 status: done
  │         更新 manifest.yaml 的 updated 日期
  │
  ├─ 失败且可自行解决 → 继续尝试，保持 🔵
  │
  └─ 失败且无法独立解决 → 🔴 blocked + blocked_reason → 留给架构师处理
```

#### 锁悬空时的续接规则

新会话读蓝图发现 🔵 任务卡（只有信息1，没有信息2）时：
1. 检查任务卡的 `files` 字段，读取相关文件的**当前代码状态**
2. 判断已完成什么、还缺什么
3. 从断点继续执行，**不重头来过**
4. 完成后补写 ✅（信息2），关锁

#### 架构师处理 blocked 任务
当 Opus 读蓝图发现 🔴 blocked 任务时：
1. 分析 `blocked_reason`，定位根因
2. 根据情况采取行动：
   - **拆**：任务本身拆得不好 → 标记原任务 abandoned → 产出新任务卡
   - **补**：缺少前置依赖 → 创建前置任务卡 → 原任务加 depends
   - **调**：架构方向需调整 → 更新模块设计/决策记录 → 重新拆任务卡
3. 新任务卡就绪后，原 blocked 任务可标记为 abandoned 或更新为 todo

### 阶段 4：回顾 — 用户在桌面 App 查看
用户打开蓝图可视化：
- 看到全景进度
- 在「下一步」面板查看可派发任务
- 点击「复制派发」→ 粘贴给新 Claude 会话

### 飞轮的反馈信号
Claude 应关注这些信号来决定是否更新蓝图：
- 用户说"这个做完了" → 标记 done
- 用户说"这个不做了" → 标记 abandoned 或删除
- 用户说"这个要拆一下" → 拆分任务卡
- 用户说"记住这个决策" → 写入决策记录
- 用户没提蓝图但在讨论功能 → 主动提议更新蓝图
- 执行模型遇到无法解决的问题 → 标记 🔴 blocked + blocked_reason
- Opus 看到 blocked 任务 → 分析原因，拆/补/调后产出新任务卡

### 对话中的复杂度漂移检测

碎片化想法在对话中自然累积，有时从样式调整演变为架构改动。Claude 应主动识别并叫停。

**漂移信号**（以下任一出现即触发）：
- 原始请求是样式/布局，但现在涉及组件 state、props 或后端命令
- 本次对话累计改动文件 ≥ 4 个，且分属不同功能区域
- 用户说了"顺便"、"既然这样"、"要不也把 XX"
- 前端改动已延伸到 DB 结构或 Rust 命令

**Claude 的应对动作**：检测到漂移信号时暂停执行，输出：

> ⚠️ 范围漂移：我们从「[原始请求]」走到了「[当前方向]」，累计涉及 [N] 个文件。建议：
> A) 完成当前这步，其余记为 💭 concept 卡待下次处理
> B) 现在拉清单，走 /architect 重新规划
> C) 继续执行，我在 session 结束前汇总成任务卡

**Session 结束汇总**：任何有代码改动但无预建任务卡的会话，结束前 Claude 应输出：

> 📋 本次会话实际改动：[文件列表 + 简述]
> 是否整理为蓝图任务卡？

## 交互质量复盘笔记

> 本章节仅适用于**开发执行阶段**（实现代码时），初始化蓝图或同步蓝图时无需执行。

每完成一张 **M 或 L 复杂度**的任务卡后，Claude 应通过 `append_project_note`（MCP 工具）写入一条结构化复盘笔记。这是飞轮外环的原始数据来源——积累足够多条后，Claude 读一遍即可识别高频坑点和高效模式。

### 笔记格式

```
【复盘】<任务标题>
任务类型: 后端命令 | 前端组件 | 数据层 | MCP工具 | 架构调整
复杂度: S | M | L
实际轮数: N轮（预估 M 轮）
是否返工: 是/否
返工原因: <若返工，一句话说明根因，如"WSL路径格式未预料">
有效策略: <本次奏效的做法，一句话>
遗留风险: <若有，一句话>
auto_applied_rules: R01, R06        ← 本次任务触发并执行了哪些规则（无则省略）
rule_effectiveness: R01=有效, R06=有效  ← 规则是否阻止了问题（有效/无效/未验证）
```

**`auto_applied_rules` 填写说明**：
- 仅记录本次任务实际触发（Claude 主动检查或提示）的规则
- 若规则触发但用户选择跳过，也应记录（用于统计触发频率）
- `rule_effectiveness=无效` 表示规则触发了但没有阻止问题，这是最有价值的信号——梦核据此降低该规则置信度

### 触发时机

| 情况 | 操作 |
|------|------|
| M/L 任务卡标记为 ✅ done | 写一条复盘笔记（source: mcp） |
| 遇到非预期的系统边界或平台差异 | 额外写一条"陷阱记录"，遗留风险填具体复现条件 |
| 同类问题第二次出现 | 在新笔记中引用旧笔记时间戳，说明"同类问题复发" |

### 示例

```
【复盘】WSL项目路径检测
任务类型: 后端命令
复杂度: M
实际轮数: 6轮（预估 2 轮）
是否返工: 是
返工原因: wsl_path 字段存的是 Windows UNC 格式（\\wsl.localhost\Ubuntu-22.04\...），而非 Linux 路径，导致 wsl 子命令收到错误参数
有效策略: 在函数入口统一用 unc_to_distro_and_linux() 转换，一次解析，全程复用
遗留风险: Path::exists() 对 \\wsl.localhost\ 路径无效，所有 WSL 路径存在性检查必须走 wsl -d distro -- test -d/f
auto_applied_rules: R10
rule_effectiveness: R10=未验证（任务开始前未触发，事后归因）
```

> 这些笔记不替代决策记录（决策记录记架构 WHY，复盘笔记记执行 HOW 和踩坑）。两者都写。

---

## 飞轮外环（跨项目数据反哺）

内环描述的是单项目的执行流程。外环负责**把多个项目的执行数据聚合起来，反哺 CONVENTIONS 本身**。

### 数据采集：usage.json 快照

每次 Claude 读取 `.blueprint/manifest.yaml`（通过炼境打开蓝图时触发），炼境自动向项目的 `.blueprint/usage.json` 追加一条当日快照：

```json
{
  "project_name": "my-project",
  "snapshots": [
    {
      "at": "2026-04-05T10:00:00Z",
      "conventions_version": "1.3.0",
      "iteration": 1,
      "modules": { "total": 22, "done": 18, "in_progress": 2, "planned": 1, "concept": 1, "blocked": 0, "stalled": [] },
      "tasks": { "total": 45, "done": 38, "in_progress": 3, "blocked": 0, "todo": 4, "dispatched": 3 },
      "blocked_reasons": []
    }
  ]
}
```

- `dispatched` = 当前满足📋可派发条件的任务数（有 acceptance + complexity S/M；files 可选）
- 节流：同一 UTC 日期只写一条，避免多次打开导致数据膨胀
- 文件存于项目本地，不上传服务器

### 数据聚合：飞轮指标

炼境跨项目读取所有 usage.json，按 `conventions_version` 分组，对每个版本队列计算 4 项指标：

| 指标 | 计算方式 | 含义 |
|------|----------|------|
| 可派发率 | dispatched / total tasks | 任务卡规划质量，越高说明任务定义越清晰 |
| 任务完成率 | done / total tasks | 整体执行进度均值 |
| 飞轮持续率 | 30天内有快照的项目比例 | 外环是否在持续运转 |
| 阻塞密度 | blocked / total tasks | 系统性阻塞程度，越低越好 |

迭代感知：同一项目若 `iteration` 值增大，说明发生了主动重构。飞轮数据层对此类项目单独计算「当前迭代完成率」，与历史累计值区分展示，避免虚高。梦核 prompt 中标注「完成率跳变项目」供 Opus 分析是健康重构还是项目失控。

### 梦核分析：记忆巩固

炼境将聚合数据 + 当前 CONVENTIONS 全文格式化为提示词，发给 **Claude Opus** 做两件事：

- **固化**：哪些跨项目重复出现的阻塞模式、哪些有效实践，值得写进 CONVENTIONS
- **遗忘**：哪些休眠项目（90天无快照）的 AI 文档可以归档，哪些 CONVENTIONS 规则已过时

### 闭环路径

两条并行的反馈路径，速度不同：

```
【快速路径 — 项目级，无需发版】
执行任务 → 复盘笔记（auto_applied_rules）
              ↓
         梦核分析项目笔记
              ↓
         输出项目私有规则草案
              ↓
         用户确认 → 写入 .blueprint/rules.md
              ↓
         下次对话立即生效

【慢速路径 — 全局级，需发版】
执行任务 → usage.json 快照
              ↓
         炼境跨项目聚合指标
              ↓
         梦核提示词 → Claude Opus 分析
              ↓
         用户/维护者审核建议
              ↓
    更新 CONVENTIONS.md 源码 + 版本号
              ↓
         发布新版炼境
              ↓
    治理面板 sync_blueprint_rules → 分发到各项目
```

> **设计意图**：快速路径响应单个项目的学习，慢速路径沉淀跨项目的共识。CONVENTIONS.md 编译进炼境二进制保证全局规则版本可追溯；rules.md 存于项目本地实现快速迭代。两条路径互补，共同构成择升环。

## 无 MCP 环境兼容（Qwen Code / 其他 AI）

部分 AI 助手（如 Qwen Code）不支持 MCP 协议，无法调用炼境工具。此时用等价文件操作代替，行为与 MCP 调用一致：

| MCP 工具 | 等价文件操作 |
|---|---|
| `get_project_blueprint` | 直接读取 `.blueprint/manifest.yaml` |
| `get_project_file` | 直接读取对应文件路径 |
| `append_project_note` | 直接编辑 `.blueprint/modules/<id>.md`，在对应任务卡末尾追加复盘笔记 |
| `get_diagnostics` | 跳过，不影响主流程 |
| `list_group_projects` | 跳过，由用户告知上下文 |

### 飞轮外环的缺口

无 MCP 环境下，`usage.json` 快照**不会被炼境自动写入**（触发写入的是炼境响应 MCP 调用时的副作用）。

影响范围：飞轮外环的跨项目统计数据本次会话不计入。飞轮内环（单项目蓝图维护、任务卡状态、复盘笔记）不受影响。

补偿方式：Qwen Code 会话结束后，在炼境中手动打开该项目蓝图，触发一次快照写入即可。

---

## 复杂功能分析流程（/architect）

当需求复杂度为 **L 级**时，在写任何代码之前执行本流程。

### 步骤

1. 读取 `manifest.yaml`，定位相关模块和依赖关系
2. 读取受影响的核心文件，理解现有实现模式和系统边界
3. 输出设计文档，格式如下：

```
## 设计决策：<功能名>

### 背景
<关联的现有模块>

### 方案选择
<2-3 个方案及取舍，标注选定方案>

### 受影响文件
- 新增：<路径> — <用途>
- 修改：<路径> — <改动说明>

### 系统边界变更
<新增接口 / 数据表 / 字段定义>

### 风险点
- <风险>：<规避方式>

### 拆解建议
建议拆为 N 张任务卡，依赖顺序：卡A → 卡B → 卡C
```

4. **不写任何代码**，设计文档经用户确认后再进入拆解流程

---

## 任务拆解流程（/splitter）

在设计文档确认后执行，产出可派发任务卡并写入蓝图文件。

### 步骤

1. 确认目标模块 id，读取对应 `modules/<id>.md`
2. 按以下原则拆解：
   - **粒度**：每张卡 complexity 必须是 S 或 M，不允许 L
   - **依赖顺序**：数据层 → 后端命令 → 前端封装 → UI 组件
   - **可派发标准**：每张卡必须有 `acceptance` + `complexity`；`files` 建议填入预期路径，有则更准确
3. 将任务卡追加到 `modules/<id>.md`
4. 更新 `manifest.yaml`：status → `planned`，更新 `updated` 日期
5. 输出拆解摘要（卡名、complexity、执行顺序）

### 质量检查
- [ ] 每张卡有 `acceptance`
- [ ] complexity 全部是 S 或 M
- [ ] 有依赖的卡填了 `depends`
- [ ] 任务卡按执行顺序排列
- [ ] `files` 尽量填入（建议项，有则帮助 agent 更快定位）

---

## 技能依赖

本蓝图工作流依赖以下 Claude Code 技能处理 L 级复杂任务：

| 技能 | 触发词 | 用途 |
|------|--------|------|
| architect | `/architect` | 复杂功能架构分析，输出设计文档 |
| splitter | `/splitter` | 将设计文档拆解为可派发任务卡 |

### 检测方式

在 Claude Code 中输入 `/architect`，若 Claude 开始执行架构分析步骤则已就绪。
若提示找不到技能，按以下方式安装。

### 安装方式

技能文件随本项目分发，位于 `.claude/skills/`：

```bash
# 复制到全局技能目录（任意项目均可使用）
cp -r .claude/skills/architect ~/.claude/skills/
cp -r .claude/skills/splitter ~/.claude/skills/

# 或仅在当前项目使用（.claude/skills/ 已存在则无需操作）
```

> 若通过炼境同步本蓝图规则，`.claude/skills/` 会随蓝图一并分发，无需手动安装。

---

## Rust 代码可测试性规范

> 本规范仅适用于**新增** Rust 函数，存量代码不强制回填。

### 强制规则

**禁止在业务函数内部调用 `pool().get()`**，改为由调用方传入连接：

```rust
// ❌ 禁止（无法在测试中注入 in-memory DB）
pub fn my_fn(args: Vec<String>) -> Result<Vec<Foo>, String> {
    let conn = crate::db::pool().get()?;
    ...
}

// ✅ 正确（依赖注入，测试可传入 in-memory DB）
pub fn my_fn(conn: &rusqlite::Connection, args: Vec<String>) -> Result<Vec<Foo>, String> {
    ...
}

// Tauri command 层负责获取连接并调用
#[tauri::command]
pub fn my_command(args: Vec<String>) -> Result<Vec<Foo>, String> {
    let conn = crate::db::pool().get().map_err(|e| e.to_string())?;
    my_fn(&conn, args)
}
```

### 测试要求

| 函数类型 | 测试要求 |
|---------|---------|
| 纯逻辑函数（无 DB） | 必须附带 `#[cfg(test)]` 测试 |
| 含 DB 的业务函数 | 必须使用依赖注入写法，附带 in-memory DB 测试 |
| Tauri command 薄包装层 | 无需测试（只做连接获取 + 函数调用） |

### 任务卡 acceptance 模板补充

含 Rust 业务逻辑的 M/L 任务卡，acceptance 须包含：

```
- [ ] 新增函数使用依赖注入（conn 作为参数）
- [ ] 附带 #[cfg(test)] 测试，覆盖主路径 + 空数据边界
- [ ] cargo test 通过
```

### 测试写法模板

```rust
#[cfg(test)]
mod tests {
    use super::*;
    use rusqlite::Connection;

    fn setup() -> Connection {
        let conn = Connection::open_in_memory().unwrap();
        // 建表语句（从 db::migrate 复制对应部分）
        conn.execute_batch("CREATE TABLE IF NOT EXISTS ...").unwrap();
        conn
    }

    #[test]
    fn test_主路径() {
        let conn = setup();
        // 插入测试数据
        // 调用函数
        // 断言结果
    }

    #[test]
    fn test_空数据返回空集合() {
        let conn = setup();
        let result = my_fn(&conn, vec![]);
        assert!(result.unwrap().is_empty());
    }
}
```

---

## 前端代码可测试性规范

> 本规范适用于**新增** TypeScript/React 代码，存量代码不强制回填。

### 测试文件位置

前端测试文件与源文件同目录，命名约定：`<filename>.test.ts(x)`。

```
src/components/MyComponent.tsx
src/components/MyComponent.test.tsx   ← 同目录、同名 + .test 后缀

src/lib/utils.ts
src/lib/utils.test.ts                ← vitest 自动发现
```

### 测试框架

使用 vitest + `describe`/`it`/`expect`，配置见项目根 `vitest.config.ts`。

### 测试要求

| 代码类型 | 测试要求 |
|---------|---------|
| 纯逻辑函数（数据处理、格式化、解析、校验） | M 级任务卡强制附带测试，覆盖主路径 + 空/边界 |
| React 组件（含状态管理、数据流） | M 级任务卡建议附带测试，至少覆盖关键交互路径 |
| 纯样式组件 / Tauri IPC 薄包装层 | 无需测试 |

### 任务卡 acceptance 模板补充

含前端纯逻辑的 M 级任务卡，acceptance 须包含：

```
- [ ] 附带 vitest 测试，覆盖主路径 + 空数据边界
- [ ] npx vitest run 全绿
```

### 测试写法模板

```typescript
import { describe, it, expect } from "vitest";
import { myFunction } from "./utils";

describe("myFunction", () => {
  it("正常路径", () => {
    expect(myFunction("input")).toBe("expected");
  });

  it("空输入不报错", () => {
    expect(myFunction("")).toBeNull();
  });

  it("非法输入返回安全默认值", () => {
    expect(myFunction("invalid")).toBeNull();
  });
});
```

---

## 项目私有规则（rules.md）

每个项目可以在 `.blueprint/rules.md` 中维护**仅对本项目生效**的推荐规则，格式与全局规则库完全相同。

### 优先级

```
项目私有规则（.blueprint/rules.md）> 全局规则（CONVENTIONS 自动推荐规则库）
```

项目私有规则更精准（来自该项目真实数据），全局规则更广泛（来自跨项目共识）。冲突时项目规则优先。

### 对话开始时的读取顺序

```
1. manifest.yaml          ← 项目全景
2. CONVENTIONS.md         ← 协议定义 + 全局规则
3. .blueprint/rules.md    ← 项目私有规则（若存在，合并应用）
```

### 梦核写入路径

梦核（飞轮阶段三启动后）分析项目复盘笔记后，除了输出 CONVENTIONS 更新建议，还应输出**项目私有规则草案**，格式如下：

```markdown
## 建议新增项目私有规则

| rule_id | 触发条件 | 自动动作 | confidence | evidence_count | derived_from |
|---------|---------|---------|-----------|---------------|-------------|
| P01 | <本项目特有触发条件> | <自动动作> | 0.70 | 3 | <复盘笔记引用> |
```

用户确认后，Claude 直接将规则写入 `.blueprint/rules.md`，**无需等待炼境发版**。这是项目级择升环与全局发版解耦的关键路径。

### rules.md 文件格式

```markdown
# 项目私有规则

> 本文件由梦核分析 + 用户确认后生成，Claude 每次对话开始时读取并合并应用。
> 规则格式与 CONVENTIONS 自动推荐规则库相同，优先级高于全局规则。

## 规则列表

### P01 — 规则标题
- **触发条件**：xxx
- **自动动作**：xxx
- **confidence**: 0.70
- **evidence_count**: 3
- **derived_from**: 复盘笔记 YYYY-MM-DD，任务"xxx"中发现
```

### 何时创建 rules.md

- 梦核首次输出项目私有规则建议时创建
- 也可手动创建，记录人工识别的项目特有模式
- 文件不存在时跳过，不影响全局规则生效

---

## 自动推荐规则库

> 本章节定义了 Claude 在开发过程中应**主动触发**的高收益决策规则。  
> 规则有置信度（confidence）和证据数（evidence_count），置信度越高越应自动执行，无需用户确认。

### 执行策略

| confidence 范围 | 执行方式 |
|----------------|---------|
| ≥ 0.80 | 直接执行，仅一行说明（"按 R01 检查..."） |
| 0.60 ~ 0.79 | 执行前单句说明原因，用户可跳过 |
| < 0.60 | 仅作提醒，不自动执行 |

置信度由梦核（阶段三启动后）根据 evidence_count 和有效率自动更新；在此之前由人工在复盘中维护。

### scope 字段

每条规则有 `scope` 字段，标明适用范围。Claude 应在应用规则前检查当前项目是否匹配：

| scope 值 | 含义 |
|---------|------|
| `universal` | 适用于任何代码项目 |
| `tauri` | 仅适用于 Tauri 项目 |
| `rust` | 仅适用于含 Rust 后端的项目 |
| `sqlite` | 仅适用于使用 SQLite 的项目 |
| `react` | 仅适用于 React 前端项目 |

多个 scope 用 `+` 连接，如 `tauri+rust`。**scope 不匹配时跳过该规则，不作提醒。**

项目私有规则（`rules.md`）无需 scope 字段，默认对本项目全部生效。

### boundaries 与 failure_cases 字段（可选）

scope 描述规则的正向适用范围，**boundaries 描述已知的反向边界**——规则在什么条件下会失效。失败案例是边界的证据来源：

```markdown
- **boundaries**: <已知不适用条件，如"squash merge 项目下 commit 数≈轮数 不成立">
- **failure_cases**:
  - YYYY-MM-DD：<触发条件> → <规则未能阻止的现象>（项目：xxx）
```

- 规则**没有 failure_cases ≠ 规则完美**，只说明边界还未被探测到
- 梦核分析时应把 failure_cases 视为最高价值信号：同一条件下反复失效 → 拆分规则为带条件的变体（原规则收窄 scope + 新增变体规则），而非简单降低 confidence
- 边界记录使经验"细化"而不是"被推翻"——这是规则库因果自洽的核心机制

### 规则列表

#### R01 — 新增 Tauri command 时检查前端封装层
- **scope**: `tauri`
- **触发条件**：在 `src-tauri/src/commands/` 下新增 `#[tauri::command]` 函数
- **自动动作**：读取 `src/lib/commands.ts`，确认是否有对应封装；缺失则提示补写，不阻止执行
- **confidence**: 0.90
- **evidence_count**: 8
- **derived_from**: 多次发生前后端接口断层（命令已实现但 commands.ts 未同步，前端调用报错）

#### R02 — 任务卡无 acceptance 时先补写再动代码
- **scope**: `universal`
- **触发条件**：任务卡 `acceptance` 字段为空或缺失，但已准备开始执行
- **自动动作**：暂停执行，根据任务描述推导验收标准草稿，请用户确认后再写第一行代码
- **confidence**: 0.92
- **evidence_count**: 18
- **derived_from**: 无验收标准导致完成定义模糊，任务频繁反复（"做完了但感觉不对"）

#### R03 — M/L 任务标记 done 后写复盘笔记
- **scope**: `universal`
- **触发条件**：M 或 L 复杂度的任务卡状态变更为 ✅ done
- **自动动作**：调用 `append_project_note` 写入复盘笔记（见"交互质量复盘笔记"章节格式）
- **confidence**: 0.88
- **evidence_count**: 24
- **derived_from**: 飞轮外环数据来源，无复盘笔记则梦核无输入，整个飞轮断链

#### R04 — 对话改动 ≥ 4 个跨功能区文件时触发漂移警告
- **scope**: `universal`
- **触发条件**：单次对话累计改动文件 ≥ 4 个，且分属不同功能区（frontend/backend/infra）
- **自动动作**：输出范围漂移提示（见"对话中的复杂度漂移检测"章节），给出 A/B/C 三个选项
- **confidence**: 0.85
- **evidence_count**: 12
- **derived_from**: 多次"样式改动演变成后端重构"的失控扩散，最终要么返工要么留下技术债

#### R05 — SQLite 涉及新表或新字段时检查 migration
- **scope**: `sqlite`
- **触发条件**：在项目中出现 `CREATE TABLE` / `ALTER TABLE` / 新增列定义
- **自动动作**：检查是否有对应 migration 逻辑；缺失则提示添加，防止旧版本升级后 schema 断裂
- **confidence**: 0.82
- **evidence_count**: 7
- **derived_from**: 数据库 schema 变更未同步 migration，导致旧安装版本升级后启动报错

#### R06 — Rust 业务函数含 DB 操作时强制依赖注入
- **scope**: `rust+sqlite`
- **触发条件**：新增 Rust 函数内部直接获取 DB 连接（`pool().get()` 或等价写法）
- **自动动作**：提示改为依赖注入写法，连接由调用方传入；command 层负责获取连接
- **confidence**: 0.93
- **evidence_count**: 15
- **derived_from**: 飞轮阶段一实现时无测试导致静默 bug 上线；依赖注入是唯一能让 in-memory DB 测试覆盖业务逻辑的方式

#### R07 — 数据关键路径函数必须附带单元测试
- **scope**: `universal`
- **触发条件**：新增函数负责数据采集、聚合、解析等关键路径（影响下游分析或展示的正确性）
- **自动动作**：在实现函数前提醒附带单元测试，覆盖正常路径 + 空数据边界；完成后验证测试全绿
- **confidence**: 0.95
- **evidence_count**: 6
- **derived_from**: 飞轮阶段一数据采集 bug 因无测试静默上线，污染所有下游分析

#### R08 — UI 状态显示必须来自真实检测
- **scope**: `universal`
- **触发条件**：前端组件显示运行状态、健康状态、操作结果等实时信息
- **自动动作**：检查对应后端是否做了真实检测而非硬编码；发现硬编码状态时标记为需修复
- **confidence**: 0.87
- **evidence_count**: 5
- **derived_from**: 设置页 MCP 状态硬编码为"运行中"，注入失败时 toast 始终显示成功——UI 掩盖真实问题

#### R09 — 自动化边界：事件触发只标 🔵，不标 ✅
- **scope**: `universal`
- **触发条件**：讨论或实现基于外部事件（git commit、CI 结果等）自动更新任务卡状态
- **自动动作**：确认自动化只将任务卡置为 🔵 in_progress，绝不自动置为 ✅ done；完成语义需人工或 Claude 验收确认
- **confidence**: 0.91
- **evidence_count**: 4
- **derived_from**: 代码提交 ≠ 功能验收通过，自动标完成导致数据与实际不符

#### R10 — 对接外部协议/API 前先验证客户端实际行为
- **scope**: `universal`
- **触发条件**：实现与外部客户端的协议对接（MCP、LSP、WebSocket、SSE、OAuth 等）
- **自动动作**：在开始实现前，先通过文档或工具（curl、抓包）确认客户端实际发出的请求格式；不基于"通用规范"假设行为
- **confidence**: 0.85
- **evidence_count**: 3
- **derived_from**: Claude Code MCP 客户端用 GET 发起 SSE 握手，炼境只接受 POST 导致 405，MCP 整体失效

#### R11 — 自动执行规则失效时必须记录失败案例
- **scope**: `universal`
- **触发条件**：confidence ≥ 0.80 的规则被自动执行后，其本应阻止的问题仍然发生（返工、报错、验收失败）
- **自动动作**：在该规则条目下追加一条 failure_case（日期 + 触发条件 + 现象 + 项目）；若为项目私有规则写入 rules.md，全局规则则在复盘笔记中记录并标注 rule_effectiveness=无效，等梦核汇总
- **confidence**: 0.80
- **evidence_count**: 1
- **derived_from**: 规则库只有正向 scope 无反例结构，失败信息流失导致置信度虚高、边界永远探测不到（2026-07-02 经验飞轮设计评审）

### 规则演进路径

```
人工识别（初始）
    ↓ evidence_count 累积 5+ 次
低置信验证期（confidence 0.60~0.79）
    ↓ 持续有效，evidence_count 15+
自动执行期（confidence ≥ 0.80）
    ↓ 发现无效或场景已变化
降级/归档（confidence 跌至 0.4 以下）
```

梦核（飞轮阶段三启动后）将根据复盘笔记中的 `auto_applied_rules` 和 `rule_effectiveness` 字段自动更新 confidence。

---

## 注意事项

- 不要删除已完成的任务卡，它们是项目历史的一部分
- 模块 id 一旦确定尽量不要修改（会影响 edges 引用）
- 每次更新后修改 manifest.yaml 顶部的 `updated` 日期
- progress 由桌面 App 自动从任务卡完成比例计算，不需要手动维护
- 当用户的操作隐含了蓝图变更但没有明说时，Claude 应主动提议更新（而非沉默）
- **批量执行完成后须做完整性检查**：同一会话内连续完成多张任务卡时，结束前必须逐一确认：① 每张已完成的子任务 status 改为 done，前缀改为 ✅；② manifest.yaml 中对应模块的 status 已同步更新。两层缺一不可。（背景：单卡两阶段流程天然同步，批量执行时容易只改模块级 status 而漏掉子任务级更新，导致 App 看板 progress 数据失真）
