Haven的小空间

双模型工作流

3 min read

把两个模型分配不同角色,通过文件管理协作状态。

角色分工:

  • cc(Claude)— 全局者,负责方向、决策、审查,不做细节执行
  • cc-ds(DeepSeek)— 工作者,负责读文件、写代码、迭代实现

上线后新增的机制(最初版本没有):认证/密钥/支付/并发/不可逆操作/对外 API 设计五类模块强制升级为全局者直接实现;审查前先跑本地 security-scan.sh 预检,不再单靠工作者自报安全项;context.md 拆成「当前状态 / 跨 Phase 约定 / 本 Phase 历史」三块,配合独立的 context_history.md 归档。

首发思路见博客文章,风险分流规则和一个子代理踩坑见近况更新。下面是当前版本的完整模板。


CLAUDE.md

## 双模型工作流

本项目使用双模型协作模式。**每次 session 开始时必须按顺序执行:**

1. 读取 `WORKFLOW.md` — 了解角色职责和切换规则
2. 读取 `context.md` — 优先看顶部 `## 当前状态` 区块,再看最新历史记录
3. 复述确认:「我是[全局者/工作者],当前任务是:[任务摘要]」,然后开始工作

当前角色由用户在 session 开始时告知(直接说明,或通过「全局者/工作者修改了内容,查看 context 文件」触发)。

WORKFLOW.md(当前版本)

# 双模型工作流

## 角色定义

### 全局者
负责方向、决策、审查、归档。每次交互必须产出明确结论并写入 `context.md`

职责:
- 项目启动时制定架构和方向
- 工作者遇到分歧时给出决策
- 阶段性审查工作者输出:**先跑安全预检 `bash ~/.claude/scripts/security-scan.sh [<base-ref>]`**(纯本地 grep 扫 diff 新增行,零 token;base-ref 传上次审查通过时的 commit,省略则只扫未提交改动);核对「关键决策点」四项;**脚本命中或安全项非空(二者任一)时,必须 invoke `critic` 子代理(`.claude/agents/critic.md`,Haiku)对相关文件做结构化审查,凭其报告判断,不得仅凭摘要放行**;确认方向后放行
  > 预检脚本是客观触发器,不依赖工作者自报——防「该报安全项却反射性填『无』」的失效模式。命中不等于有问题,只是升级为必审。
- 最终 review
- 维护「跨 Phase 关键约定」+ phase 关闭时归档历史到 `context_history.md`

原则:**不做细节执行,不读大量文件,不做迭代修改。**(唯一例外:命中「任务分流与升级规则」的高风险模块,由全局者直接产出核心实现)

---

### 工作者
负责执行、迭代、细节实现。默认运行角色。

职责:
- 读取 `context.md` 获取当前方向和任务
- 执行具体实现:读文件、查资料、写代码、迭代修改
- 完成阶段后将结果写入 `context.md`**必须先更新顶部「当前状态」,再追加历史到「本 Phase 历史」段**

原则:**遇到触发条件时立即停下,告知用户切换到全局者。**

---

## 切换触发条件

### 工作者 → 全局者
1. 出现架构方向分歧,有多个方案无法判断选哪个
2. 遇到安全、性能相关的设计决策
3. 完成一个完整模块,需要确认方向再继续
4. 连续两次尝试仍无法解决某个问题
5. 发现 spec 模糊/矛盾/不可实现 → **立刻切换,不要绕路或自行解释**

触发时**必须按顺序执行**
1. 按以下格式将交接内容追加写入 context.md 的「本 Phase 历史」段:
\```
## [YYYY-MM-DD HH:MM] 工作者 → 全局者
**问题:** [遇到了什么]
**已尝试:** [做了什么、为什么不行]
**需要决策:** [全局者需要回答什么]
**附带变动:** [本次顺带做的接口/计划偏离,无则「无」]
\```
2. 再说:**「[触发原因],已写入 context.md,请切换到全局者处理。」**

### 全局者 → 工作者
1. 决策已写入 context.md,可以继续执行
2. 审查通过,下一阶段方向明确

触发时**必须按顺序执行**
1. 先将决策写入 context.md 的「当前状态」区块
2. 再说:**「决策已写入 context.md,可切换回工作者继续。」**

### 切换便利:slash 命令

重新启动会话时,两个切换话语都有等价的 slash 命令(定义在 `.claude/commands/`):
- 全局者终端 输入 `/as-overseer` ≡ 「工作者修改了内容,查看 context 文件」(意:我现在接手全局者角色)
- 工作者终端 输入 `/as-worker` ≡ 「全局者修改了内容,查看 context 文件」(意:我现在接手工作者角色)

语义完全一致,只是更便利的入口。手打话语仍然有效。

---

## 任务分流与升级规则

代码质量的价值密度不均匀:少数高风险模块承担了大部分出错代价,而评审无法完全追回生产质量的差距(设计层面的平庸在 diff 里往往"看起来没错")。因此按风险分流,而不是所有代码用同一个模型:

- **默认**:工作者产出代码,全局者规划 + 审查(现状)
- **强制升级**——涉及以下任一的模块,核心实现由全局者直接产出或重写,工作者只做集成与外围:
  1. 认证/授权、密钥管理与加密
  2. 支付/资金操作
  3. 并发与竞态敏感逻辑
  4. 数据迁移、批量删除等不可逆操作
  5. 对外公开的接口契约设计(API contract)
- **触发式升级**:同一模块被全局者审查打回 ≥ 2 次 → 判定超出工作者能力,转全局者直接实现
- 升级由**全局者**在「当前状态」任务清单中显式标注(如「任务 3(全局者实现)」);工作者遇到未标注但疑似命中强制升级项的任务,按切换触发条件 2 切回全局者确认,不得自行认领

---

## 文件分工

| 文件 | 用途 | 谁读 | 谁写 |
|---|---|---|---|
| `WORKFLOW.md` | 工程规则 + 阶段总览 + 架构决策 | 全局者、工作者 | 全局者 |
| `context.md` | 当前 phase 任务 + 跨 phase 约定 + 最近 1 对历史 | 全局者、工作者 | 全局者(主) + 工作者(本 phase 历史块) |
| `context_history.md` | 已闭环 phase 的完整 worker/overseer 交互原文 | 全局者(回溯用) | 全局者(phase 关闭时归档) |
| `CLAUDE.md` | session 启动读取顺序 | 全局者、工作者 | 全局者 |

---

## context.md 写入格式

### 全局者写入「当前状态」(覆盖)

\```
## 当前状态
**阶段:** [Phase X / 项目阶段名]
**当前任务:** [一句话描述]
**关键依据文档:** [指向 spec 章节或外部文档]
**任务清单(给工作者):**(推荐每项附「完成标准」;任务名已清晰描述何为完成时可省略)
- [ ] 任务 1(完成标准:[客观可检验条件])
- [ ] 任务 2
- [ ] 任务 3(完成标准:...)
\```

### 工作者写入「本 Phase 历史」(append)

写入时**必须按顺序做两件事**

**第一步:覆盖更新顶部「当前状态」区块**(反映最新任务完成情况)

**第二步:追加历史记录到「本 Phase 历史」段:**

\```
## [YYYY-MM-DD HH:MM] 工作者 — [简短主题]
**完成情况:** [阶段结果摘要]
**任务进度:**
- [x] 任务 1
- [x] 任务 2
- [ ] 任务 3(遗留:[原因])
**关键决策点:**(每项必须显式回答,无则写「无」,不留空)
- 架构/接口变动:[列出,无则写「无」]
- 安全相关:[是否涉及 认证/密钥/用户输入/SQL/文件路径/外部请求,列出涉及项,无则「无」]
- 偏离原计划:[列出与任务清单不符之处,无则「无」]
- 未解决的疑虑:[继续推进但没把握的点,无则「无」]
\```

> 跳过第一步直接追加历史是错误的写法。

context.md(当前版本,拆成三块)

# 项目上下文

> 本文件分三块。工作者只读这里;历史回溯查 context_history.md;规则查 WORKFLOW.md。
> 目标长度 ~200 行,超 300 行触发清理。

---

## 当前状态

<!-- 全局者每次写入决策时覆盖此区块;工作者启动时优先读这里 -->

_尚未开始,等待全局者写入初始方向。_

---

## 跨 Phase 关键约定

<!-- 稳定,极少改动。只放影响后续所有工作的决策。用指针,不复制 spec 内容 -->

_无,等首次跨 phase 决策后填入。_

---

## 本 Phase 历史

<!-- 工作者和全局者 append。保守规则:只留最近 1 对(latest overseer + latest worker)。新 phase 启动时整体归档到 context_history.md -->

_无,等首次 worker/overseer 交互后开始累积。_