# AI原生DevOps Platform 架构设计 v2.6

**版本**: v2.6(Shared Workspace + Blackboard 架构)
**基于**: architecture-v2.md + v2.0 AI Native 调研 + 技术验证
**作者**: 庞统(副军师)
**日期**: 2026-05-15

---

## 变更历史

| 版本 | 日期 | 变更内容 |
|------|------|---------|
| v2.0 | 2026-05-04 | 初始版本:SQLite 4表 + 状态机 + DAG 引擎 |
| v2.6 | 2026-05-15 | **架构重构**:Shared Workspace(Blackboard)取代 DAG 引擎为编排核心 |
| v2.6.1 | 2026-05-15 | 司马懿评审反馈 + Mail 退役决策 + 质量门控 + 决策记录 + 工程修正 |
| v2.6.2 | 2026-05-15 | 课题1设计决策:三层执行模型、续杯机制、AI驱动retry、Guardrail体系、must_haves三件套、分级审查矩阵 |
| v2.6.2.1 | 2026-05-15 | 司马懿评审反馈:L2/L3区分标准、timeout修正、outputs关联attempt、Scope Guard异步、risk_level自动 |
| v2.6.3 | 2026-05-15 | 课题2设计决策：Tick核心+Inbox JSONL加速、Handoff Comment无缝接手、L1/L2/L3对应Opal-Bridge Fidelity、黑板AI Native内容规范+三层约束体系(Schema校验+Skill引导+L1截取)、依赖驱动并行/串行、Phase规划更新 |
| v2.6.4 | 2026-05-15 | 课题3设计决策：分级审查流水线(四级风险→三/二/一阶段)、审查协议注册表(Review Protocol Registry)、反驳权(Rebuttal Phase)、reviews表结构化存储、声明式guardrails.yaml、Full Agent vs Subagent vs Daemon直接执行判据、对抗辩论模式 |
| v2.6.5 | 2026-05-15 | 课题4设计决策：模板组件库(+custom)替代固定DAG、四层上下文架构(L0铁律/L1角色/L2引擎注入三段式/L3被动参考)、prompt_templates按角色拼装、L2按角色精确注入不多不少、L3 Skill description四要素优化写法 |
| v2.6.6 | 2026-05-15 | 课题7+9设计决策：四种交互模式(沉浸观察/轻触确认/即时对话/被动通知)、推送级别分级(🔴🟡🟢🔵)、三层信息架构(L1一眼/L2看板/L3详情)、5页Dashboard(任务看板/全局监控/产出档案/系统配置/AI Briefing) |
| v2.6.7 | 2026-05-15 | 课题6设计决策：经验三种载体(Memory→Skill→Rule)、两级蒸馏(实时一级+周期二级)、验证(格式+内容+实用性)、四层架构反哺(Daemon注入+被动参考)、experiences表、Skill生命周期(draft→active→deprecated) |
| v2.6.8 | 2026-05-16 | 课题10结论：不需要复杂压缩/摘要、续杯问题已由课题2+4解决、单黑板单Daemon多任务并行、Context预算35-60K远小于128K、用户级多项目待课题11解决 |
| v2.6.9 | 2026-05-16 | 7项目调研结论纳入：Guardrail验证脚本层(Aider)、对抗性审计映射(claude-goal→L1/L2/L3)、防偏离三防线+Runaway Guard、双重Hook(OpenClaw+moziplus)、Shadow Checkpoint(Cline)、潜在课题(模型策略/信任分级/Worktree隔离)、Blackboard Map按需触发 |
| v2.6.9.1 | 2026-05-16 | 司马懿评审回应：PRD目标不改+架构记录差距、blocked状态保留+设计完整、verification_commands安全模型明确(exec approvals)、Daemon逻辑健康自检纳入§14 |
| v2.6.10 | 2026-05-16 | 课题11多项目：方案C单Daemon多数据库 + per-project线程并发 + ActiveAgentCounter异步计数器 + session命名规则(sequential复用/parallel独立) + 三层资源控制 + 项目归档/删除安全流程 |
| v2.6.11 | 2026-05-16 | 课题7+9方案完成：v1.0已有11个Tab全部保留(仅任务看板重设计)、Checkpoint三种交互、推送SSE+降级轮询、AI Briefing日报/周报、项目切换器、推送通知中心 |
| v2.6.12 | 2026-05-16 | 全量遗留清理(51项→0) + 课题3四项新方案(对抗辩论/评审Schema/反驳权/调度判据) + 司马懿评审通过(comments表comment_type) + 工具链课题初始化 + 技术架构/部署架构重写(v2.6.2) |
| v2.8 | 2026-05-18 | v2.8 状态增强：新增 paused/escalated/waiting_human 3状态（共11个）+ 归档机制 + M3 Checkpoint/Artifact + 前端两行筛选栏 + 卡片快捷按钮 |

### 课题 1-2 遗留 TODO(需后续课题解决)

| # | 待解决事项 | 归属课题 | 说明 |
|---|----------|---------|------|
| ~~T1-1~~ | ~~spawn sub 是否阻塞?需要调查~~ | ~~课题 2~~ | ✅ 课题 2 解决:不阻塞,signal file 异步 |
| ~~T1-2~~ | ~~事件驱动取代 polling tick~~ | ~~课题 2~~ | ✅ 课题 2 解决:双层事件架构 |
| ~~T1-3~~ | ~~依赖推进(done→自动解锁下游)~~ | ~~课题 2~~ | ✅ 课题 2 解决:task_completed 事件即时解锁 |
| ~~T2-1~~ | ~~files_modified 冲突检测~~ | ~~课题 2~~ | ✅ D2-4 决策:不做,Agent 评论自然协调 |
| ~~T2-2~~ | ~~Auto-compact~~ | ~~课题 2~~ | ✅ D2-6 决策:不做,隔离 session 天然无 context rot |
| ~~T1-4~~ | ~~Agent 间自主协商机制~~ | ~~课题 3~~ | ✅ 课题3解决:审查协议+反驳权+评论协商 |
| ~~T1-5~~ | ~~Scope Guard 的 Skill 定义~~ | ~~课题 4~~ | ✅ 课题4解决:executor.md 步骤2(scope_declaration) |
| ~~T1-6~~ | ~~truths 验证的具体实现~~ | ~~课题 4~~ | ✅ 课题4解决:executor.md 步骤1+Plan Checker(plan_check.yaml) |
| ~~T1-7~~ | ~~outputs attempt_number 过滤规则~~ | ~~课题 4~~ | ✅ 课题4解决:executor.md 步骤4(output提交)+Daemon build_bootstrap() |
| ~~T1-8~~ | ~~状态机细化(review 轮次、sub_status)~~ | ~~课题 3~~ | ✅ 课题3解决:§9.7状态机对齐 |
| ~~T2-3~~ | ~~blackboard.py 写操作自动写 inbox JSONL~~ | ~~Phase 1~~ | ✅ 开发实现 |
| ~~T2-4~~ | ~~Tick Loop + Inbox JSONL Watcher~~ | ~~Phase 1~~ | ✅ 开发实现 |
| ~~T2-5~~ | ~~L2/L3 分层读取 API~~ | ~~Phase 2~~ | ✅ 开发实现 |
| ~~T2-6~~ | ~~仓库级上下文（Agent Context Pack）~~ | ~~Phase 3~~ | ✅ P3 保留，不合并不关闭 |
| ~~T2-7~~ | ~~Handoff Comment 的 Skill 引导~~ | ~~Phase 2~~ | ✅ 课题4解决:executor.md 步骤5写死 |
| ~~T2-8~~ | ~~Handoff Comment 的 Skill 解析规则~~ | ~~课题 4~~ | ✅ 课题4解决:executor.md "前序信息"部分+schemas/handoff.schema.json |

### 课题 4 Skill 体系设计 TODO

> **课题4设计决策**：关键操作不靠 Skill 被动触发，走引擎注入（L2 prompt_templates）。以下 28 项全部通过 prompt_templates/ + review_protocols/ + schemas/ 覆盖。此表保留作为设计推导留痕。
>
> **覆盖映射**：
> - S-01~S-12（执行者操作）→ prompt_templates/executor.md
> - S-13~S-20（审查者操作）→ prompt_templates/reviewer.md + review_protocols/*.yaml
> - S-21~S-27（庞统操作）→ prompt_templates/planner.md / adjudicator.md
> - S-28（L1 消息构建）→ Daemon build_bootstrap() 代码
>
> 详见课题4方案：`docs/design/topic4-decomposition-skill-proposal.md` D4-6/D4-7

| # | Skill 内容 | 适用角色 | Phase | 来源 | 覆盖方式 |
|---|----------|---------|-------|------|----------|
| S-01 | blackboard.py CLI 使用手册 | 所有 Agent | P1 | 课题1 §5.2 | ✅ executor.md 各步骤中写死 |
| S-02 | L1→L2/L3 按需读取判断 | 所有 Agent | P2 | 课题2 §4.4 | ✅ executor.md "可选参考"部分 |
| S-03 | 写 Handoff Comment（格式+时机） | 所有 Agent | P1 | 课题2 §5.1 | ✅ executor.md 步骤5 |
| S-04 | 读 Handoff Comment（利用上一个 Agent 交接） | 所有 Agent | P2 | 课题2 §5.1 | ✅ executor.md "前序信息"部分 |
| S-05 | 写 observation（时机+severity 格式） | 所有 Agent | P2 | 课题1 §4.7 | ✅ executor.md 步骤3 |
| S-06 | 写 decision（时机+rationale 格式） | 所有 Agent | P2 | 课题1 §9.4 | ✅ executor.md 步骤2 |
| S-07 | 写 output 的 Schema 约束 | 所有 Agent | P1 | 课题2 §3.7 | ✅ executor.md 步骤4 + schemas/ |
| S-08 | Guardrail 打回时的处理流程 | 执行者 | P2 | 课题3 §9.3 | ✅ executor.md + guardrails.yaml |
| S-09 | @mention 使用规范 | 所有 Agent | P2 | 课题1 §5.2 | ✅ executor.md 步骤3 |
| S-10 | claim 后写 scope_declaration（格式+内容） | 执行者 | P1 | 课题1 §4.7 | ✅ executor.md 步骤2（含JSON格式） |
| S-11 | must_haves 三件套自检（truths/artifacts/constraints） | 执行者 | P1 | 课题1 §9 | ✅ executor.md 步骤1 |
| S-12 | 收到 review needs_revision 的反驳流程（ACCEPT/REJECT/PARTIAL） | 执行者 | P2 | 课题3 §9.5 | ✅ rebuttal.md |
| S-13 | 审查者 Investigation Protocol 五阶段执行 | 审查者 | P2 | 课题3 §9.4 | ✅ reviewer.md 五步骤 |
| S-14 | 多视角审查方法（代码/方案/分析三套视角集） | 审查者 | P2 | 课题3 §9.4 | ✅ reviewer.md + review_protocols/ |
| S-15 | 写 review 的 Schema 约束（verdict+evidence） | 审查者 | P2 | 课题3 §9.6 | ✅ reviewer.md + schemas/ |
| S-16 | 信心度自评（confidence 打分标准） | 审查者 | P2 | 课题3 §9.6 | ✅ reviewer.md 步骤5（自审） |
| S-17 | 收到反驳（REJECT）后的评估方法 | 审查者 | P2 | 课题3 §9.5 | ✅ reviewer.md（反方回应处理） |
| S-18 | plan_review 协议（假设提取/pre-mortem/依赖审计） | 审查者 | P2 | 课题3 §9.4 | ✅ review_protocols/plan_review.yaml |
| S-19 | output_review 协议（需求追踪/缺口分析） | 审查者 | P2 | 课题3 §9.4 | ✅ review_protocols/output_review.yaml |
| S-20 | analysis_review 协议（逻辑跳跃/数据来源） | 审查者 | P2 | 课题3 §9.4 | ✅ review_protocols/analysis_review.yaml |
| S-21 | 创建任务（truths/artifacts/constraints 定义） | 庞统 | P1 | 课题1 §9 | ✅ planner.md |
| S-22 | 风险等级自动判断（task_type→risk_level） | 庞统 | P1 | 课题3 §9.2 | ✅ planner.md（映射规则） |
| S-23 | 挑战者选择（按任务类型选挑战者） | 庞统 | P2 | 课题3 §9.10 | ✅ planner.md（选择表） |
| S-24 | 对抗辩论裁决方法 | 庞统 | P3 | 课题3 §9.10 | ✅ adjudicator.md |
| S-25 | escalated 任务的用户沟通 | 庞统 | P3 | 课题3 §9.7 | ✅ planner.md / adjudicator.md |
| S-26 | confidence 低时的升级判断 | 庞统 | P2 | 课题3 T3-5 | ✅ reviewer.md（< 0.7 升级庞统） |
| S-27 | 任务拆解方法（依赖声明/子任务创建） | 庞统 | P2 | 课题1 §5.1 | ✅ planner.md（四步+组件库+PlanChecker） |
| S-28 | L1 消息构建逻辑 | 庞统/Daemon | P1 | 课题2 §4.4 | ✅ Daemon build_bootstrap() 代码 |
| ~~T2-9~~ | ~~inbox 并发写入的竞态处理~~ | ~~Phase 1 验证~~ | ✅ 已解决：truncate（清空不删除）替代 unlink（删除），实测 200 次并发写入 0 丢失。演进方向：向 webhook 实时化走 |
| ~~T2-10~~ | ~~inbox 文件的 rotate/truncate 策略~~ | ~~Phase 2~~ | ✅ 关闭：Inbox 每秒被清空，正常运行不膨胀。Daemon 崩溃积压也仅 ~200KB/1000条 |
| ~~T2-11~~ | ~~Tick 频率 30s vs 60s 的性能验证~~ | ~~开发后实测~~ | ✅ 开发后实测 |
| ~~T2-12~~ | ~~CLI Schema 校验的 schemas/ 目录定义~~ | ~~Phase 1~~ | ✅ 开发实现 |

### 课题 3 遗留 TODO

| # | 待解决事项 | 归属 | 说明 |
|---|----------|------|------|
| ~~T3-1~~ | ~~reviews 表的 CLI 命令~~ | ~~Phase 2~~ | ✅ 方案已定，开发实现 |
| ~~T3-2~~ | ~~Guardrail YAML 解析 + 执行引擎~~ | ~~Phase 2~~ | ✅ 方案已定，开发实现 |
| ~~T3-3~~ | ~~对抗辩论模式的具体黑板协议~~ | ~~Phase 3~~ | ✅ 方案已定（topic3 §5.1），仅用户明确要求时启用 |
| ~~T3-4~~ | ~~挑战者池的选择策略~~ | ~~Phase 2~~ | ✅ 方案已定，开发实现 |
| ~~T3-5~~ | ~~confidence 低于阈值自动升级~~ | ~~Phase 2~~ | ✅ 方案已定，开发实现 |
| ~~T3-6~~ | ~~评审详情文件的 Schema 定义~~ | ~~Phase 2~~ | ✅ 方案已定（topic3 §5.2），待司马懿评审确认 |
| ~~T3-7~~ | ~~low 风险任务 Guardrail 自动通过~~ | ~~Phase 2~~ | ✅ 方案已定，开发实现 |
| ~~T3-8~~ | ~~Review Protocol 模板文件编写~~ | ~~Phase 2~~ | ✅ 方案已定，开发实现 |
| ~~T3-9~~ | ~~反驳权 Daemon 流控~~ | ~~Phase 2~~ | ✅ 方案已定（topic3 §5.3），轮次上限兜底不设超时 |
| ~~T3-10~~ | ~~Agent 调度判据~~ | ~~Phase 2~~ | ✅ 方案已定（topic3 §5.4），配置表驱动非 AI 判断 |

---

## 1. v2.6 核心变革:从 DAG 状态机到 Shared Workspace

### 1.1 为什么变?

v2.0 的核心是 **DAG 引擎 + 状态机 + 邮件通信**,本质是给 AI 团队做了一套 ERP:
- 编排是确定性状态机(固定流程)
- 交互是点按钮(Dashboard)
- Agent 间靠邮件异步通信(信息分散在 mail 目录)
- 人的参与密度不变(全程驾驶)

v2.6 的核心是 **Shared Workspace(Blackboard)+ Agent 自主决策 + Daemon 投递**:
- 编排是 AI agent 在黑板上自主领活(动态协作)
- 交互是自然语言对话
- Agent 间通过黑板共享一切(信息集中在任务空间)
- 人只做方向决策和验收

### 1.2 核心原则

> **黑板是唯一真相源,所有 agent 读它、想、行动,写回结果。Daemon 是投递员,不是决策者。**

1. **Agent 决策,Daemon 执行** - 庞统做 plan、张飞领任务、关羽发现风险,都写在黑板上。Daemon 读黑板,执行 spawn/通知。
2. **产出在黑板,不在邮件** - 所有任务产出、讨论、观察都在任务的黑板空间里,Sanguo Mail 不介入任务协作。
3. **Daemon 不阻塞 Agent** - Daemon 是常驻管家,定期 tick 检查黑板,spawn agent 执行,不占用任何 agent 的主 session。
4. **Session 用完即清** - Agent 通过 `openclaw agent --agent <id> --session-id <uuid>` spawn 隔离 session,执行完 daemon 存档 jsonl 并清理 sessions.json。
5. **双入口,对等地位** - Agent 对话和 Dashboard 是两个对等入口,共享同一套黑板数据。Dashboard 是 AI Native 的可视化入口,不是降级的监控面板。

---

## 2. 架构总览

```
┌─────────────────────────────────────────────────────────────┐
│                      用户 / 触发器                            │
│                   (Web / CLI / Cron)                         │
└──────────────────────────┬──────────────────────────────────┘
                           │ 写入黑板或触发 daemon
┌──────────────────────────▼──────────────────────────────────┐
│                    Shared Workspace(黑板)                    │
│                                                               │
│  ┌────────────────────────────────────────────────────────┐  │
│  │              SQLite (blackboard.db)                     │  │
│  │  tasks / comments / outputs / agents / events          │  │
│  │  原子读写(propose→validate→commit 或 SQLite 事务)     │  │
│  └────────────────────────────────────────────────────────┘  │
│                                                               │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐       │
│  │ 任务列表  │ │ 评论线程  │ │ 产出空间  │ │ 讨论区域  │       │
│  └──────────┘ └──────────┘ └──────────┘ └──────────┘       │
└──────────────────────────┬──────────────────────────────────┘
                           │ daemon tick 读写
┌──────────────────────────▼──────────────────────────────────┐
│                    Daemon(管家)                              │
│                                                               │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────────┐  │
│  │ Tick 循环    │  │ Session 管理  │  │ 健康检查          │  │
│  │ (60s 轮询)   │  │ spawn/archive │  │ zombie/reclaim   │  │
│  │ 读黑板→决策  │  │ /cleanup      │  │ /stale 任务      │  │
│  └──────┬───────┘  └──────┬───────┘  └──────────────────┘  │
│         │                 │                                   │
│  Daemon 只做三件事:       │                                   │
│  1. 读黑板,发现需要介入的  │                                   │
│  2. Spawn 对应 agent       │                                   │
│  3. 清理完成的 session     │                                   │
└──────────────────────────┬──────────────────────────────────┘
                           │ openclaw agent --agent <id> --session-id <uuid>
                           │ 执行完 → 存档 jsonl → 清理 sessions.json
┌──────────────────────────▼──────────────────────────────────┐
│                   Agent 层(将军们)                          │
│                                                               │
│  Agent 不常驻。被 spawn 时:                                   │
│  1. 读黑板 → 了解全局状态                                     │
│  2. 想和做 → 根据职责自主决策                                  │
│  3. 写回黑板 → 产出、评论、领任务                              │
│  4. 退出 → session 被 daemon 清理                             │
│                                                               │
│  ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐    │
│  │庞统  │ │司马懿│ │姜维  │ │关羽  │ │张飞  │ │赵云  │    │
│  │策划  │ │质量  │ │平台  │ │风控  │ │编码  │ │数据  │    │
│  └──────┘ └──────┘ └──────┘ └──────┘ └──────┘ └──────┘    │
│                                                               │
│  每个 Agent: SOUL.md + IDENTITY.md + Skills + Workspace      │
│  Agent 主 session 不参与任务执行(不被污染)                     │
└─────────────────────────────────────────────────────────────┘
```

### 关键区别:v2.0 vs v2.6

| 维度 | v2.0 | v2.6 |
|------|------|------|
| 编排核心 | DAG 引擎 + 状态机 | Blackboard(Shared Workspace) |
| 决策者 | Daemon(状态机驱动) | Agent(在黑板上自主决策) |
| Daemon 角色 | 调度器(决定谁干什么) | 投递员(执行黑板上的决策) |
| Agent 通信 | Sanguo Mail(异步邮件) | 黑板 Comment 线程(共享空间) |
| 信息位置 | 分散(mail + task目录 + session) | 集中(黑板 SQLite) |
| Agent 生命周期 | 固定节点执行 | Spawn 隔离 session,用完即清 |
| 通知机制 | Mail 轮询 | Daemon tick + spawn |
| 协作模式 | 指令式(庞统分配→将军执行) | 自主式(看黑板→领活→写回) |

---

## 3. Shared Workspace(黑板)设计

### 3.1 参考系统对比

| 系统 | 存储 | 原子性 | 讨论 | 状态机 | 发现 |
|------|------|--------|------|--------|------|
| Claude Code Agent Teams | JSON 文件 | 无(last-write-wins) | inbox 点对点 | pending/in_progress/completed | Agent 轮询 |
| Hermes Kanban v0.13 | SQLite | SQLite 事务 | Comment 线程 | 7 状态完整机 | Dispatcher 60s tick |
| Network-AI | Markdown 文件 | flock 三阶段提交 | signal key | 无 | Agent 主动读 |
| agent-blackboard | SQLite + Ontology | SQLite 事务 | 本体条目 | 无 | Coordinator 分发 |
| **我们的方案** | **SQLite** | **SQLite 事务** | **Comment 线程** | **简化状态机** | **Daemon tick** |

### 3.2 SQLite Schema

```sql
-- ===== 任务表 =====
CREATE TABLE IF NOT EXISTS tasks (
    id TEXT PRIMARY KEY,                    -- task-001
    title TEXT NOT NULL,
    description TEXT,
    status TEXT NOT NULL DEFAULT 'pending',
    CHECK (status IN ('pending','claimed','working','review','done','failed','blocked','cancelled')),

    -- 分配(谁领了或被指派)
    assignee TEXT,                          -- agent id: zhangfei-dev
    assigned_by TEXT,                       -- 谁分配的:pangtong-fujunshi / user

    -- 依赖
    depends_on TEXT,                        -- JSON array of task IDs
    parent_task TEXT,                       -- 父任务(子任务分解时)

    -- 优先级和类型
    priority INTEGER NOT NULL DEFAULT 5,   -- 1(最高)-10(最低)
    task_type TEXT,                         -- coding/review/data/deploy/research/discuss

    -- 时间
    created_at TEXT NOT NULL DEFAULT (datetime('now')),
    updated_at TEXT NOT NULL DEFAULT (datetime('now')),
    claimed_at TEXT,
    started_at TEXT,
    completed_at TEXT,
    deadline TEXT,

    -- 重试
    retry_count INTEGER NOT NULL DEFAULT 0,
    max_retries INTEGER NOT NULL DEFAULT 2,

    -- must_haves 与风险等级(课题1设计决策)
    must_haves TEXT,                          -- JSON: {truths: [], artifacts: [], constraints: []}
    risk_level TEXT DEFAULT 'standard',       -- high/standard/low/research
    estimated_duration_minutes INTEGER        -- 预估工时(续杯硬上限 = 3x 此值)
);

CREATE INDEX IF NOT EXISTS idx_tasks_status ON tasks(status);
CREATE INDEX IF NOT EXISTS idx_tasks_assignee ON tasks(assignee);
CREATE INDEX IF NOT EXISTS idx_tasks_parent ON tasks(parent_task);

-- ===== 评论线程表 =====
-- 参考 Hermes kanban_comment:追加写入,所有参与者可见
CREATE TABLE IF NOT EXISTS comments (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    task_id TEXT NOT NULL,
    author TEXT NOT NULL,                   -- agent id 或 'user'
    comment_type TEXT NOT NULL DEFAULT 'general',  -- general/handoff/observation/rebuttal/rebuttal_response/debate_argument/debate_rebuttal/debate_judgment
    body TEXT NOT NULL,
    mentions TEXT,                          -- JSON array: ["zhangfei-dev", "guanyu-dev"]
    created_at TEXT NOT NULL DEFAULT (datetime('now')),

    FOREIGN KEY (task_id) REFERENCES tasks(id),
    CHECK (comment_type IN ('general', 'handoff', 'observation', 'rebuttal', 'rebuttal_response', 'debate_argument', 'debate_rebuttal', 'debate_judgment'))
);

CREATE INDEX IF NOT EXISTS idx_comments_task ON comments(task_id);
CREATE INDEX IF NOT EXISTS idx_comments_type ON comments(task_id, comment_type);
CREATE INDEX IF NOT EXISTS idx_comments_author ON comments(author);
-- 注意:mentions 是 JSON 数组,无法直接建索引。daemon tick 查询用 json_each(mentions)。
-- 数据量小时够用,后续可拆 comment_mentions 关联表优化。

-- ===== 产出表 =====
CREATE TABLE IF NOT EXISTS outputs (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    task_id TEXT NOT NULL,
    agent TEXT NOT NULL,                    -- 谁写的
    output_type TEXT NOT NULL,              -- code/document/data/config/other
    title TEXT NOT NULL,
    content_path TEXT,                      -- 文件路径(产出物在 task 目录下)
    summary TEXT,                           -- 一句话摘要
    metadata TEXT,                          -- JSON: {files_changed, lines_added, ...}
    attempt_number INTEGER DEFAULT 1,       -- 关联 task_attempts.attempt_number
    created_at TEXT NOT NULL DEFAULT (datetime('now')),

    FOREIGN KEY (task_id) REFERENCES tasks(id)
);

CREATE INDEX IF NOT EXISTS idx_outputs_task ON outputs(task_id);

-- ===== 决策记录表 =====
-- Agent 执行过程中的关键决策必须记录。哪怕是自己做的决策也要填一条。
CREATE TABLE IF NOT EXISTS decisions (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    task_id TEXT NOT NULL,
    decider TEXT NOT NULL,                  -- 谁做的决策
    decision TEXT NOT NULL,                 -- 决策内容:"选 A 方案"
    rationale TEXT NOT NULL,                -- 为什么:"B 方案内存开销更大"
    alternatives TEXT,                      -- JSON array: 被排除的选项
    created_at TEXT NOT NULL DEFAULT (datetime('now')),

    FOREIGN KEY (task_id) REFERENCES tasks(id)
);

CREATE INDEX IF NOT EXISTS idx_decisions_task ON decisions(task_id);

-- ===== 观察表 =====
-- Agent 执行过程中发现的问题、风险、建议
CREATE TABLE IF NOT EXISTS observations (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    task_id TEXT NOT NULL,
    observer TEXT NOT NULL,                 -- 谁观察到的
    severity TEXT NOT NULL DEFAULT 'info',
    CHECK (severity IN ('blocking','warning','info','audit')),
    body TEXT NOT NULL,
    resolved_by TEXT,                       -- 谁处理的
    resolved_at TEXT,                       -- 何时处理的
    created_at TEXT NOT NULL DEFAULT (datetime('now')),

    FOREIGN KEY (task_id) REFERENCES tasks(id)
);

-- ===== 事件日志(审计追踪)=====
CREATE TABLE IF NOT EXISTS events (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    task_id TEXT,
    agent TEXT,
    event_type TEXT NOT NULL,
    detail TEXT,                            -- JSON
    created_at TEXT NOT NULL DEFAULT (datetime('now'))
);

CREATE INDEX IF NOT EXISTS idx_events_task ON events(task_id);
CREATE INDEX IF NOT EXISTS idx_events_time ON events(created_at);

-- 合法 event_type 清单:
-- 任务:task_created, task_claimed, task_started, task_completed, task_failed,
--       task_blocked, task_unblocked, task_reviewed, task_cancelled, task_retried
-- 协作:comment_added, output_written, observation_added, decision_recorded
-- Agent:agent_spawned, agent_completed, agent_zombie_detected
-- Session:session_spawned, session_archived, session_cleanup
-- 系统:daemon_tick, daemon_manual_tick

-- ===== Agent 注册表 =====
CREATE TABLE IF NOT EXISTS agents (
    agent_id TEXT PRIMARY KEY,
    role TEXT,
    current_status TEXT DEFAULT 'idle',     -- idle/working/offline
    current_task TEXT,
    last_active TEXT,
    capabilities TEXT                       -- JSON array: ["coding", "review", "deploy"]
);

-- ===== 任务尝试记录(参考 Hermes task_runs)=====
CREATE TABLE IF NOT EXISTS task_attempts (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    task_id TEXT NOT NULL,
    attempt_number INTEGER NOT NULL,
    agent TEXT NOT NULL,
    outcome TEXT NOT NULL,  -- completed/blocked/crashed/timed_out/spawn_failed/reclaimed
    exit_code INTEGER,
    log_path TEXT,
    summary TEXT,
    metadata TEXT,  -- JSON: {duration_seconds, token_count, ...}
    started_at TEXT NOT NULL DEFAULT (datetime('now')),
    completed_at TEXT,

    FOREIGN KEY (task_id) REFERENCES tasks(id)
);

CREATE INDEX IF NOT EXISTS idx_attempts_task ON task_attempts(task_id);

-- agents 表更新规则:
-- Agent claim 任务时:自己更新 current_status='working', current_task=task_id
-- Agent 完成退出时:daemon 更新 current_status='idle', current_task=NULL
-- Daemon tick 检测到 zombie:daemon 更新 current_status='offline'
```

**连接配置:**

```python
def get_connection():
    conn = sqlite3.connect(str(DB_PATH))
    conn.row_factory = sqlite3.Row
    conn.execute("PRAGMA journal_mode=WAL")
    conn.execute("PRAGMA foreign_keys=ON")
    conn.execute("PRAGMA busy_timeout=5000")
    return conn
```

### 3.3 状态机（v2.8：11 个状态）

```
pending → claimed → working → review → done
  ↑         │ ↕        ├→ blocked ──┘  ├→ failed
  │         │ paused   ├→ paused      └→ cancelled
  └─────────┘          ├→ escalated
                       └→ waiting_human  ← M3 Checkpoint

  (review→pending: 审核不通过,打回重做)
  (review→waiting_human: 审查阶段需人工裁定)
  (blocked→pending: 阻塞解除)
  (blocked→escalated: 阻塞升级求助)
  (failed→pending: 重试)
  (failed→escalated: 失败升级求助)
  (escalated→working: 用户介入后恢复)
  (waiting_human→working: Checkpoint reject)
  (waiting_human→done: verify Checkpoint approve)
```

**v2.8 变更:** v2.6 有 8 个状态,v2.8 新增 3 个: paused(用户暂停)、escalated(Agent 升级求助)、waiting_human(Checkpoint 人工确认)。

| 状态 | 含义 | 谁触发 | 调度 | 聚合 |
|------|------|--------|------|------|
| pending | 待领取 | 任何 Agent 或用户创建 | ✅ 正常调度 | ✅ 参与 |
| claimed | 已认领 | Agent 自己或被指派 | ✅ 超时回收 | ✅ 参与 |
| working | 执行中 | Agent | ✅ 超时监控 | ✅ 参与 |
| review | 待审核 | Agent 完成产出 | ✅ review 调度 | ✅ 参与 |
| **paused** | **已暂停** | **用户主动** | **❌ 跳过** | **❌ 不参与** |
| **escalated** | **已升级** | **Agent 求助** | **❌ 跳过** | **✅ 视同 working** |
| **waiting_human** | **等人工** | **Agent Checkpoint** | **❌ 跳过** | **✅ 视同 working** |
| done | 完成 | 审核通过 | 终态 | ✅ 参与 |
| failed | 失败 | Agent 或 daemon | ❌ 不调度 | ✅ 参与 |
| blocked | 需要帮助 | Agent | ❌ 不调度 | ✅ 参与 |
| cancelled | 取消 | 用户 | 终态 | ❌ 不参与 |

**聚合规则（v2.8）:** 优先级 escalated > waiting_human > review > working/claimed > pending > failed > blocked。paused/cancelled 不参与。全部 done → done。

**完整合法流转矩阵:**

```python
VALID_TRANSITIONS = {
    "pending":       {"claimed", "cancelled"},
    "claimed":       {"working", "paused", "pending", "cancelled"},
    "working":       {"review", "blocked", "failed", "paused", "escalated", "waiting_human", "cancelled"},
    "paused":        {"working", "cancelled"},
    "review":        {"done", "pending", "failed", "escalated", "waiting_human", "cancelled"},
    "blocked":       {"pending", "escalated", "cancelled"},
    "failed":        {"pending", "escalated", "cancelled"},
    "escalated":     {"working", "pending", "cancelled"},
    "waiting_human": {"working", "done", "cancelled"},
    "done":          set(),                                       # 终态
    "cancelled":     set(),                                       # 终态
}
```

**字段迁移（v2.8）:** `escalated` 从布尔字段改为 status 判断。DB 保留 `escalated INTEGER` 做向后兼容，前端/Ticker 改用 `task.status == 'escalated'`。

**归档机制（v2.8）:** tasks 表新增 `archived INTEGER DEFAULT 0`、`archived_at TEXT`。归档不改变状态，只影响前端显示（默认不显示已归档任务）。

**Checkpoint 机制（M3）:** Agent 执行到需人工确认的节点 → 创建 checkpoint + 设置 waiting_human → 用户 approve/reject → 自动推进状态。详见 `docs/design/v2.8-state-enhancement.md`。

### 3.4 原子操作

**任务认领(claim)** - 原子 CAS,防止两个人同时领:

```python
def claim_task(task_id: str, agent_id: str) -> bool:
    conn = get_connection()
    try:
        cursor = conn.execute(
            "UPDATE tasks SET status='claimed', assignee=?, claimed_at=datetime('now') "
            "WHERE id=? AND status='pending' AND (assignee IS NULL OR assignee=?)",
            (agent_id, task_id, agent_id)
        )
        conn.commit()
        return cursor.rowcount > 0  # 0 表示被别人抢了或不是指定分配给自己的人
    finally:
        conn.close()
```

**产出写入** - SQLite 事务保证原子:

```python
def write_output(task_id: str, agent_id: str, output: dict):
    conn = get_connection()
    try:
        conn.execute("BEGIN IMMEDIATE")  # 立即获取写锁
        conn.execute(
            "INSERT INTO outputs (task_id, agent, output_type, title, content_path, summary, metadata) "
            "VALUES (?, ?, ?, ?, ?, ?, ?)",
            (task_id, agent_id, output['type'], output['title'],
             output['path'], output['summary'], json.dumps(output.get('metadata', {})))
        )
        conn.execute(
            "INSERT INTO events (task_id, agent, event_type, detail) VALUES (?, ?, 'output_written', ?)",
            (task_id, agent_id, json.dumps({'output_id': output['title']}))
        )
        conn.commit()
    finally:
        conn.close()
```

### 3.5 评论线程(讨论机制)

参考 Hermes 的 `kanban_comment` 模式:

```python
def add_comment(task_id: str, author: str, body: str, mentions: list = None):
    conn = get_connection()
    try:
        conn.execute(
            "INSERT INTO comments (task_id, author, body, mentions) VALUES (?, ?, ?, ?)",
            (task_id, author, body, json.dumps(mentions or []))
        )
        conn.execute(
            "INSERT INTO events (task_id, agent, event_type, detail) VALUES (?, ?, 'commented', ?)",
            (task_id, author, json.dumps({'body_preview': body[:100], 'mentions': mentions}))
        )
        conn.commit()
    finally:
        conn.close()
```

**讨论示例:**

```
[16:30 庞统] 张飞,你的实现方案我看了,回测数据量大时内存会爆。
              关羽,从风控角度也看看? @关羽 @张飞
[16:35 关羽] 同意。建议加分批加载机制,单批不超过 50 万条。
[16:40 张飞] 收到,改成分批加载。预计 30 分钟。
[16:55 庞统] @张飞 注意止损逻辑也需要同步改,分批后止损触发时机变了。
[17:10 张飞] 完成。产出在 output-zhangfei-v2.md。
```

**核心原则:评论都在黑板上,不在任何 agent 的 session 里。Agent 的 session 是临时的。**

### 3.6 竞态解决

任务认领的竞态通过 SQLite 原子 CAS 解决(先到先得)。

职责冲突的解决(张飞和关羽都认为自己该做某个任务):
1. **默认:先到先得** - SQLite CAS,谁先 claim 谁做
2. **升级:庞统仲裁** - 如果争议,评论中 @庞统 请求仲裁
3. **最终:用户拍板** - @user 请求用户决定

不需要复杂的分布式共识--职责分工已经自然避免了大部分冲突。

### 3.7 黑板是索引不是仓库(AI Native 内容规范)

**核心原则:黑板只存元数据 + 摘要 + 文件路径,不存大段文本内容。**

设计推导(课题 2):
- Network-AI 的核心洞察:Agent 只读黑板摘要,详细数据在文件中
- Claude Code 的 file reference 模式:不内联,只引用
- agent-chorus 的 Context Pack 实验证明:结构化上下文让 Agent 文件打开量降 70%、token 消耗降 60%、零生产风险答案
- Opal-Bridge 的 Fidelity 三档:无损/摘要/混合,传递时按需降档
- 一个典型任务全量黑板信息 ~1100-1750 tokens,极端 ~4000 tokens--远小于 128K context
- 问题不是空间不够,而是**信号噪声比**:全量注入让 Agent 在无关信息上浪费注意力

**AI Native 内容规范--不做硬限制,做软引导:**

传统做法是给每个字段设长度上限(如 comments.body ≤ 2000 字符),这是 CRUD 应用的思维。
AI Native 的做法是:Agent 是智能体,有能力判断"这段分析应该写文件还是直接写评论"。规范是指导性的,不是强制性的。

- **不做硬限制**--不设字段长度上限,不截断,不报错
- **做软引导**--Agent 的 Skill 中写"评论应简洁明了,大段分析写文件后在评论中给路径"
- **做传递优化**--L1 传递时自动截取(最近 3 条评论、每条 100 字符),这是传递层面的优化,不是存储层面的限制
- **做信息分层**--黑板上的 comments 表存完整内容(不截断),但 L1 传递时只取摘要

**为什么这样做是 AI Native**:
1. Agent 是智能体,不是 API 客户端--它有能力判断"这段分析应该写文件还是直接写评论"
2. 如果硬限制导致信息丢失,Agent 会绕过限制(拆成多条评论、用文件存储),反而更混乱
3. 真正需要控制的是传递时的信息量(L1 预算),不是存储时的信息量

**黑板上"必要信息"的定义(指导性)**:

| 类别 | 上黑板 | 不上黑板 |
|------|--------|----------|
| 决策 | ✅ 谁、选了什么、为什么 | ❌ 完整备选方案对比表 |
| 产出 | ✅ title + summary + content_path | ❌ 代码全文、数据文件 |
| 状态 | ✅ 当前 status + 最新 observation | ❌ 完整事件日志(可归档) |
| 讨论 | ✅ 结论 + 关键论据 | ❌ 来回辩论的完整过程 |
| 风险 | ✅ severity + 一句话描述 | ❌ 详细影响分析报告 |

**防爆炸机制**:
- 产出物只存路径(outputs.content_path)
- 事件日志有 TTL(events 表定期归档旧数据)
- 大段分析建议写文件,黑板只存摘要+路径

#### 三层约束体系（AI Native 结构化约束）

Skill 软引导的问题是"可看可不看"，等于没有约束。数据库硬限制是传统 CRUD 思维。中间地带是 **CLI 层 Schema 校验**——参考 agent-chorus 的 JSON Schema 模式（每个操作都有 `schemas/*.schema.json`），在写入接口层校验结构。

| 层 | 机制 | 约束力 | 适用对象 |
|---|------|--------|----------|
| **Schema 校验** | blackboard.py CLI 写入时校验 JSON Schema | 强（不符合返回明确错误） | 结构化操作（handoff / output / decide / observe） |
| **Skill 引导** | Agent Skill 中的行为规范文本 | 弱（可看可不看） | 非结构化操作（普通评论、讨论） |
| **L1 截取** | Daemon 构建 L1 时自动截取 | 代码层面，Agent 无感 | 传递优化 |

**为什么这是 AI Native**：
1. Schema 是可执行文档——Agent 不需要读 Skill 就能知道格式要求（CLI 错误信息会告诉它缺了什么）
2. 错误信息是建设性的——"Handoff must include 'completed' field" 让 Agent 知道该补什么
3. 约束的是结构，不是内容——不限制写多长，只限制必须包含哪些字段
4. Agent 可以自主决定深度——可选字段可以不写
5. 和 OpenAI Agent SDK 的 handoff `input_type` 同理——Pydantic schema 校验交接数据

**Schema 定义**（`schemas/` 目录）：

```json
// schemas/handoff.schema.json
{
  "type": "object",
  "required": ["completed", "artifacts"],
  "properties": {
    "completed": { "type": "string", "description": "完成了什么" },
    "artifacts": {
      "type": "array",
      "items": { "type": "string" },
      "description": "产出物路径列表"
    },
    "remaining": { "type": "string", "description": "未完成事项（可选）" },
    "next_steps": { "type": "string", "description": "对接手者的建议（可选）" }
  }
}

// schemas/observe.schema.json
{
  "type": "object",
  "required": ["severity", "body"],
  "properties": {
    "severity": {
      "type": "string",
      "enum": ["info", "warning", "critical"],
      "description": "info=只记录不触发; warning=下次tick触发庞统; critical=立即spawn庞统"
    },
    "body": { "type": "string", "description": "风险描述" }
  }
}
```

**severity 枚举与处理方式对齐**（与 §4.7 Guardrail 体系一致）：

| severity | Daemon 处理 | 对应 Guardrail 行为 |
|----------|-----------|-------------------|
| `info` | 只记录，不触发 | 不介入 |
| `warning` | 下次 tick 统一处理 | spawn 庞统（L3）判断 |
| `critical` | inbox 通知 → 立即 spawn 庞统 | 立即介入 |

| 操作 | Schema 文件 | 必填字段 | Schema 校验 | CLI 附加校验 |
|------|-----------|---------|------------|------------|
| `--handoff` | handoff.schema.json | completed + artifacts | 结构完整，类型正确 | artifacts 中路径是否存在 |
| `--output` | output.schema.json | summary + content_path | summary 非空字符串 | content_path 文件是否存在 |
| `--decide` | decide.schema.json | decision + rationale | 两个字段非空字符串 | 无 |
| `--observe` | observe.schema.json | severity + body | severity 枚举值(info/warning/critical) | 无 |
| `--comment`（普通） | 无 | body | 无 Schema 校验 | 无 |

**Agent 使用方式**：
```bash
# 结构化操作：CLI 校验 Schema
blackboard.py comment --task task-001 --author zhangfei-dev \
  --handoff '{"completed": "分批加载实现", "artifacts": ["task-001/output.md"], "remaining": "止损逻辑"}'
# 校验失败 → 返回具体错误："Handoff must include 'completed' field"
# 校验通过 → 写入 comments 表，body 自动格式化为结构化文本

# 普通评论：无 Schema 校验
blackboard.py comment --task task-001 --author zhangfei-dev \
  --body "@赵云 task-002 需要分钟线数据"
```

**落地到 schema（存储层）**:
- `outputs` 表：`content_path` + `summary`，不存文件内容
- `comments` 表：`body` 存完整内容（不截断），handoff 类型自动格式化
- `decisions` 表：`decision` + `rationale` 是结构化文本
- `observations` 表：`body` 是风险描述

Agent 获取信息的分层策略（L1/L2/L3）详见 §4.4，对应 Opal-Bridge Fidelity 三档。

---

## 4. Daemon(管家)设计

### 4.1 Daemon 的角色定位

> **Daemon 是投递员,不是决策者。所有决策发生在黑板上,daemon 只执行。**

Daemon 做三件事:
1. **读黑板** - 定期 tick,检查黑板状态
2. **Spawn Agent** - 根据黑板上的指示,spawn 对应的 agent
3. **清理 Session** - agent 执行完后,存档 jsonl + 清理 sessions.json

Daemon **不做**:
- ❌ 不决定谁做什么(agent 自己决定或庞统在黑板上分配)
- ❌ 不维护状态机(黑板就是状态)
- ❌ 不做业务逻辑(不解析产出、不做评审)

**三层执行模型**:Daemon 的操作按成本和复杂度分为三层:

| 层级 | 方式 | 成本 | 适用场景 | 例子 |
|------|------|------|---------|------|
| **L1 Daemon 直接操作** | SQLite 读写、文件操作 | 几乎为零 | 纯机械动作 | 更新状态、记录事件、机械验证(文件存在、JSON格式、字段非空) |
| **L2 spawn sub** | `openclaw agent --agent <id> --session-id <uuid>` | 轻量(隔离 session,单任务) | 轻量 AI 判断 | scope guard、格式校验、快速评估、假死 reminder |
| **L3 run agent** | spawn 完整 Agent 到黑板上工作 | 完整(读黑板+思考+写回) | 重度 AI 工作 | 庞统拆解、张飞编码、司马懿 review、庞统纠错 |

关键区别:
- L2 的 sub 是一次性、单任务的("帮我检查这个输出是否在 scope 内"),执行完就退出
- L3 的 agent 是完整的黑板参与者(读全局、自主决策、写回多个表)

**L2 与 L3 的区分标准**:是否读黑板全局。
- L2:不读黑板全局上下文,只拿当前任务的特定字段做判断。spawn 时传递局部数据(如 scope_declaration 文本 + task.truths),sub 返回结果后退出。
- L3:读黑板全局(tasks + comments + outputs + decisions + observations),做全局决策。spawn 时只传任务 ID + 触发原因,Agent 自己读黑板。

这个区分决定了 spawn 时的消息内容--L2 传数据,L3 传指针。

### 4.2 事件驱动架构(课题 2 设计决策)

#### 设计推导过程

**三个参考系统的做法**:

| 系统 | 架构 | 事件通知方式 | 启示 |
|------|------|------------|------|
| **open-multi-agent** | 单进程 TypeScript | 纯 EventEmitter--`queue.on('task:ready', handler)`。TaskQueue 内部维护 listeners Map,complete() 时同步触发 emit。零基础设施 | 和我们的黑板同构:TaskQueue.complete() = 我们的任务完成,unblockDependents() = 我们的依赖解锁 |
| **agent-chorus** | 多进程(Claude/Codex/Gemini 各自独立) | 本地 JSONL 文件队列--`chorus send` 写入 `.agent-chorus/messages/<target>.jsonl`,`chorus messages --agent <self> --clear` 读并清空。纯文件系统,无网络 | Standup+Conclude 模式:Agent 开始时读 inbox,结束时广播状态。JSONL inbox 做跨进程通信 |
| **Edict** | 分布式(API Gateway + Orchestrator + Agent Pool) | Redis Streams Event Bus--`task.created` 等主题 + WebSocket 推送 Dashboard | 我们是单机单进程,不需要 Redis |

**推导结论**:
1. open-multi-agent 证明:单进程内 EventEmitter 完全够用,但它是单进程,我们是跨进程
2. agent-chorus 证明:跨进程通信用 JSONL 文件就行,不需要 HTTP/Redis/MQ
3. Edict 的 Redis Streams 是分布式场景所需,我们不需要
4. **真正需要即时响应的场景只有 4 个**:task_completed / task_failed / @mention / user_action。其他 ≤30s 延迟完全可接受
5. **60s Tick 本身不是问题,问题是 Tick 的效率**--应该 Tick 是核心,加速器可选

**用户反馈与设计迭代**:
- 初始设计:Signal File 跨进程通知 → 用户质疑"Signal File 存在的意义是什么"
- 第二版:HTTP 端点 → 用户要求"基于优秀实践推导,不是拍脑袋换方案"
- 最终版:Tick 核心 + Inbox JSONL 加速(agent-chorus 模式)--基于三个参考系统的实际代码推导

#### D2-1:Tick 核心 + Inbox 加速(最终方案)

```
┌──────────────────────────────────────────────────────────────────┐
│                    Daemon (Python asyncio)                       │
│                                                                   │
│  核心:Tick Loop(30s 主循环)                                     │
│  ┌─────────────────────────────────────────────────────────────┐ │
│  │ 读黑板全量状态(SQLite 查询)                                  │ │
│  │ 发现需要处理的(mention / blocked / done → pending)           │ │
│  │ 执行对应操作(spawn / 通知 / 清理)                             │ │
│  │ 健康检查(zombie / stale / heartbeat)                         │ │
│  │                                                               │ │
│  │ 设计推导:Hermes 60s tick 证明 polling 可靠稳定。              │ │
│  │ 我们从 60s 降到 30s,因为黑板查询比 Hermes 轻量。              │ │
│  └─────────────────────────────────────────────────────────────┘ │
│          ↑                                                        │
│  加速:Inbox JSONL(agent-chorus 模式)                           │
│  ┌─────────────────────────────────────────────────────────────┐ │
│  │ Agent 写黑板后,可选:追加一行 JSON 到 daemon inbox             │ │
│  │ Daemon 主循环每 1s 检查 inbox 是否有新内容                     │ │
│  │ 有新内容 → 立即执行一次 mini-tick(只处理触发的事件)            │ │
│  │ 处理完清空 inbox                                               │ │
│  │                                                               │ │
│  │ 设计推导:agent-chorus 用 JSONL inbox 做跨 Agent 通信,         │ │
│  │ 我们用 JSONL inbox 做 Agent→Daemon 通知。同理同构。            │ │
│  │ inbox 是加速器,不是核心。Tick 兜底所有场景。                    │ │
│  └─────────────────────────────────────────────────────────────┘ │
│          ↑                                                        │
│  恢复:启动时全量扫描                                              │
│  ┌─────────────────────────────────────────────────────────────┐ │
│  │ Daemon 重启后立即做一次完整 Tick(PM2 自动重启)                │ │
│  │ 消除重启后的 30s 空窗                                          │ │
│  │ 不需要 EventBus 持久化--黑板(SQLite)是唯一真相源              │ │
│  └─────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────┘
```

**为什么不选的替代方案**:
- EventBus + Signal File(初始设计):Signal File 需要额外的扫描/读/删循环,增加了耦合链
- HTTP 端点(第二版):引入网络依赖,Daemon 需要跑 HTTP 服务,不够简单
- Redis pub/sub(Edict 方案):引入新依赖,v2.6 已去掉 Redis;我们不需要分布式
- SQLite update-hook:需要 C API 绑定
- fswatch/watchdog:跨平台兼容性差

**Inbox JSONL 具体实现**(参考 agent-chorus `chorus send` 模式):

```python
# blackboard.py 写完 SQLite 后,可选追加一行 JSON
INBOX_PATH = Path("~/.sanguo_projects/sanguo_moziplus_v2/inbox/daemon.jsonl")

# 写入格式(参考 agent-chorus message schema: from/to/timestamp/content/cwd)
async def notify_daemon(event_type: str, task_id: str, agent: str):
    line = json.dumps({
        "from": agent,
        "to": "daemon",
        "timestamp": datetime.now(timezone.utc).isoformat(),
        "event": event_type,     # comment_added / task_completed / task_failed
        "task_id": task_id,
    })
    async with aiofiles.open(INBOX_PATH, mode='a') as f:
        await f.write(line + '\n')

# Daemon 主循环中检查 inbox
async def check_inbox():
    if not INBOX_PATH.exists():
        return
    lines = INBOX_PATH.read_text().strip().split('\n')
    INBOX_PATH.write_text('')  # truncate：清空内容不删除文件，避免并发追加写入时文件不存在
    for line in lines:
        msg = json.loads(line)
        await handle_event(msg['event'], msg['task_id'], msg['from'])
```

**Daemon 主循环**:

```python
async def daemon_main_loop():
    # 启动时全量扫描
    await full_tick()

    while True:
        # 1. 检查 inbox(每 1s)
        await check_inbox()  # 有内容则立即执行 mini-tick

        # 2. 定期 Tick(每 30s)
        if time.time() - last_tick > 30:
            await full_tick()
            last_tick = time.time()

        await asyncio.sleep(1)
```

#### D2-2:依赖声明的并行/串行自动决策

> **设计推导**:open-multi-agent 的 TaskQueue.complete() → unblockDependents() 是核心模式--complete→auto-unlock,纯依赖声明驱动。其 scheduler.ts 还提供了 4 种调度策略(round-robin / least-busy / capability-match / dependency-first)。

**串行触发链**(Tick + Inbox 加速版):
```
Agent A 完成 task-001
  → 写黑板 outputs + 更新 status → done + 写 handoff comment
  → 通知 Daemon(inbox JSONL)
  → Daemon 下次循环(~1s 内)收到通知 → mini-tick:
      查询所有 depends_on 包含 task-001 的 pending 任务
      → task-002 depends_on: [task-001],检查 task-001 done ✅
      → spawn Agent B 执行 task-002
  (如果 inbox 通知丢失 → 30s Tick 兜底补上)
```

**并行**:`depends_on` 为空且 assignee 不同的任务,自然并行(Daemon 分别 spawn)。不需要额外逻辑。

**不做 files_modified 冲突检测**(D2-4):Agent 通过黑板评论自然协调("我在改 main.py,你别碰"),不需要系统强制。Scope Guard(课题 1)作为兜底。实际覆盖:depends_on 覆盖 80%+ 的显式依赖场景,边角场景通过黑板评论 + 庞统仲裁补充。

#### 与课题 1 的兼容性

| 课题 1 设计 | 事件驱动后变化 | 改善 |
|-----------|--------------|------|
| 续杯机制 | task_completed 通知加速依赖解锁 | @mention 从 ≤60s 降到 ≤1s |
| retry 由 AI 决策 | task_failed 通知加速 retry 链 | 庞统更快介入 |
| Guardrail 吹哨人 | observation 写入后通知 Daemon | Daemon 即时感知问题 |
| 三层执行模型 | 不变,Tick/inbox 处理仍按 L1/L2/L3 分层 | ✅ 一致 |

### 4.3 Session 生命周期

```
1. Daemon spawn
   openclaw agent --agent zhangfei-dev --session-id <uuid> \
     --message "请检查黑板 task-001..."
   ↓
2. Agent 执行
   - 读黑板(SQLite 查询)
   - 做任务(编码/审核/数据分析)
   - 写回黑板(产出、评论、状态更新)
   ↓
3. Agent 退出(自然结束)
   ↓
4. Daemon 清理
   - mv <session_id>.jsonl → task-001/archive/
   - mv <session_id>.trajectory.jsonl → task-001/archive/
   - 编辑 sessions.json 删除该 session 记录
```

**技术验证结论:**
- `openclaw agent --agent <id> --session-id <uuid>` 可创建完全隔离的 session ✅
- 直接编辑 `sessions.json` 可安全删除 session 记录 ✅(已验证)
- Gateway WS `sessions.delete` 需要 `operator.admin` scope(token 模式不授予,不可用)❌
- 回退方案:直接编辑 `sessions.json` 是安全可靠的 ✅

### 4.4 Agent Spawn 的上下文分层传递(课题 2 设计决策)

> **设计推导**:GSD Wave Execution 证明隔离 session + 新鲜 context > 单一 session + 压缩。Claude Code 的 file reference 模式证明"引用而非内联"是最优策略。Opal-Bridge 的 Fidelity 三档提供了理论框架。agent-chorus 的 Context Pack 实验证明结构化上下文让 Agent 效率提升 60-70%。问题不是 context 不够大,而是信号噪声比。

**L1/L2/L3 对应 Opal-Bridge Fidelity 三档**:

| Opal-Bridge Fidelity | 我们的映射 | 场景 |
|---------------------|----------|------|
| Mode A:无损(完整上下文) | L1 + L2 + L3 | 复杂任务,Agent 需要完整了解讨论历史和产出 |
| Mode B:LLM 摘要 | L1 + L2 | 标准任务,核心信息 + 扩展摘要 |
| Mode C:混合保留最近N条 | L1 | 简单任务,只传核心,Agent 按需取更多 |

Agent 自己决定用哪个 Fidelity 档位--收到 L1 后判断信息是否足够,不够就 L2/L3。

**D2-5:三层上下文传递(L1 必传 / L2 按需 / L3 按需)**

| 层级 | 内容 | Token 估算 | 谁决定 |
|------|------|-----------|--------|
| **L1(spawn message)** | 任务核心 + 角色 + 触发原因 + 依赖状态 + 最近评论 + must_haves | ~300-500 | Daemon 自动 |
| **L2(CLI 按需)** | 完整评论线程 + 产出摘要 + 决策记录 + 观察记录 | ~500-1500 | Agent 自主决定 |
| **L3(文件按需)** | 产出物文件完整内容 + 完整事件日志 + 子任务详情 | ~2000-10000 | Agent 自主决定 |

**L1 Spawn Message 模板**:

```python
def build_spawn_message_L1(task_id: str, agent_id: str, trigger: str) -> str:
    task = get_task(task_id)

    # 依赖状态摘要(1行/依赖任务)
    deps_status = []
    for dep_id in json.loads(task['depends_on'] or '[]'):
        dep = get_task(dep_id)
        deps_status.append(f"  {dep_id}: {dep['status']} - {dep['title']}")

    # 最近 3 条评论摘要(截断 100 字符)
    recent_comments = get_comments(task_id, limit=3)
    comments_str = ""
    for c in recent_comments:
        comments_str += f"  [{c['created_at'][:16]} {c['author']}] {c['body'][:100]}\n"

    # must_haves 摘要
    must_haves = json.loads(task.get('must_haves') or '{}')
    truths_str = ', '.join(must_haves.get('truths', []))

    return f"""黑板任务通知(L1):
任务:{task['title']}({task['id']})
状态:{task['status']} | 类型:{task['task_type']} | 风险:{task['risk_level']}
触发原因:{trigger}
描述:{task['description'] or '(无)'}
验收标准(truths):{truths_str or '(未定义)'}

依赖状态:
{chr(10).join(deps_status) if deps_status else '  (无依赖)'}

最近评论:
{comments_str if comments_str else '  (无评论)'}

请使用以下命令获取更多信息:
  L2(扩展):blackboard.py read --task {task_id} --level L2
  L3(全量产出):blackboard.py read --task {task_id} --type outputs
"""
```

**D2-6:不需要 Auto-compact**:v2.6 的 Agent 每次 spawn 都是隔离的新鲜 session,天然没有 context rot。唯一可能有累积的是庞统主 session(长期在线协调),属 Phase 3 优化。

**D2-7:Context 预算分配**(128K 模型):

| 组件 | 预算 | 说明 |
|------|------|------|
| System Prompt + SOUL.md + IDENTITY.md | ~3K-5K tokens | 固定开销 |
| Skills + AGENTS.md | ~2K-4K tokens | 固定开销 |
| L1 spawn message | ~300-500 tokens | 必传 |
| L2 黑板扩展(按需) | ~500-1500 tokens | Agent 自主决定 |
| L3 产出物文件(按需) | ~2K-10K tokens | Agent 自主决定 |
| 工作空间(Agent 思考+输出) | ~30K-50K tokens | 预留 |
| **总计** | **~40K-70K tokens** | 远小于 128K,安全 |

### 4.5 续杯与心跳

参考 v1.0 实践 + Hermes v0.13 Claim TTL。

**正常流(大多数情况):**
1. Agent spawn → 开始工作
2. Agent 每个关键进展写黑板 observation(既是进度汇报,也是心跳信号)
3. Daemon tick 看到 working 状态 + 有新 observation → 不干预(健康状态)
4. Agent 完成产出 → 写 output + 状态流转 → Daemon 检测到继续下一步

**异常流:**

| 情况 | Daemon 检测到 | 行为 | 层级 |
|------|-------------|------|------|
| Agent 有进展 | 黑板有新 observations | 不干预(无限续) | L1 |
| Agent 没进展但 session 活跃 | 无新 observations 但 session 还在 | 不干预(可能正在思考) | L1 |
| ↑ 判断信号:`observations 最后写入时间 < estimated_duration_minutes`,纯 L1 查询,不依赖 AI 判断 | | | |
| timeout(agent run 返回超时)+ 产出达标 | agent run 返回超时 + outputs 表有内容 | 幻觉门控验证产出 → 通过则继续流转 | L1→L2 |
| timeout(agent run 返回超时)+ 产出不达标 | agent run 返回超时 + outputs 为空 | L2 spawn sub 发 reminder 让 Agent 继续(假死处理) | L2 |
| timeout + 产出不达标 + reminder 后仍无进展 | 二次 timeout | 回收到 pending,记录 failure_detail | L1 |
| 非timeout 错误(进程退出) | 进程已死 | 进入 AI 纠错流程 | L3 |
| 硬上限超时 | working 状态超过 3x 预估工时 | 强制回收,记录事件 | L1 |

**设计推导**:
- v1.0 实践证明:看结果不看过程(即使 CLI 报错/超时,产出文件存在且有效就算成功)
- 续命和重试是两个独立预算:续命(Agent有进度→无限续),重试(Agent真挂→有限次)
- Hermes 的 Claim TTL(默认15分钟)提供了超时回收的参考值

**timeout 的检测**:timeout 信号来自 `openclaw agent --agent <id>` 的返回值(阻塞调用)。Agent 在执行过程中通过写黑板 observations 维持活跃信号--Daemon tick 检查 observations 的最后写入时间,如果有新 observation 说明 Agent 还在工作。但最终判断 Agent 是否超时,以 agent run 的返回值为准。

reminder 后的硬时间上限:reminder 后如果超过 `estimated_duration_minutes` 仍未完成(从 reminder 时间算起),才回收任务。

### 4.6 AI 驱动的 Retry(纠错协商)

参考 v1.0 _handle_blocked_node() + Hermes task_runs + Claude Code Teams "before retrying, answer what failed"。

**核心原则**:Retry 原因由 AI 判断,Daemon 只执行。

**流程:**

1. Agent 失败(产出 status=failed 或 Daemon 检测到异常终止)
2. Daemon 不判断原因,只在黑板上记录这次 attempt(task_runs 模式,每次 attempt 独立记录)
3. Daemon spawn 庞统(L3)看黑板上的失败记录 + 之前所有 attempts
4. 庞统在黑板上写决策(四种选择之一):
   - "同一 Agent 重试" + 失败原因分析 + 改进建议
   - "换 Agent 重试" + 为什么换 + 新 Agent 优势
   - "任务需要用户介入" + 卡在哪 + 建议
   - "任务无法完成,建议取消" + 为什么
5. Daemon 读庞统决策,执行对应操作
6. 如果重试后仍失败 → 新 attempt 记录 → 再次 spawn 庞统
7. Circuit breaker:同一 task 总 attempt 数达到 N 次(默认3次,不区分是哪个 Agent)→ 自动 block + 通知用户。理由:3 次尝试都不成功说明问题在任务本身而非 Agent 能力。

**失败记录**:谁记录什么?

| 记录者 | 记录内容 | 黑板位置 |
|--------|---------|---------|
| Daemon | 机械类失败(进程退出码、超时) | events 表,event_type=task_failed |
| 司马懿 | 内容类失败(评审不通过) | reviews 表(verdict=needs_revision + issues) |
| 庞统 | 方向类失败(需求偏离) | decisions 表(重规划原因) |
| Agent 自己 | 能力不足/专业外,主动报告失败 | comments 表(说明原因)+ tasks status→failed |
| Agent(重试时) | 新 attempt 的产出 | outputs 表(带 attempt_number) |

**Agent 重试时能看到什么**:黑板上的 events(失败记录)+ reviews(评审意见)+ comments(讨论)。全部在黑板上,spawn 时自然读到。

**设计推导**:
- v1.0 实践:庞统分析原因 → 司马懿 challenge → 三轮协商 → 执行,方向正确但由引擎硬编码调用
- v2.6 改进:Agent 在黑板上自主协商(需要事件驱动支持,见课题2),Daemon 只 spawn 不调度
- Hermes task_runs:每次 attempt 独立记录(attempt_number, outcome, log_path, exit_code),可追溯可审计

### 4.7 Guardrail 体系(吹哨人机制)

参考 OpenAI Agent SDK OutputGuardrail + GSD must_haves + v1.0 M4 Guard 机制。

**核心原则**:Guardrail 是吹哨人不是终结者。检测到问题写黑板(observation),触发后续 AI 判断链。决策权在黑板上,执行权在 Daemon。

**三个 Guardrail:**

| Guardrail | 触发时机 | 检测方式 | 发现问题后 |
|-----------|---------|---------|-----------|
| **Scope Guard** | Agent claim 任务后在工作过程中写 decisions(scope 相关)时 | L2 sub 异步对比 scope_declaration vs task.truths | 写 observation(severity=warning),Daemon 下次 tick 触发庞统判断 |
| **Output Guard** | Agent 写 output 时 | L1 机械检查(文件存在、格式正确、字段非空)+ L2 语义检查 | 机械失败直接打回,语义问题写 observation |
| **Format Guard** | Agent 写任何结构化数据时 | L1 JSON Schema 校验 | 格式错误直接打回重做 |

**后续动作链(问题升级):**

```
Guardrail 检测到问题 → 写黑板 observation
  ↓
Daemon tick 读到 observation
  ↓
根据 severity 分级处理:
  - blocking → L3 立即 spawn 庞统
  - warning → L3 spawn 庞统(下次 tick 统一处理)
  - info → 只记录,不触发
  ↓
庞统在黑板上写决策:
  - "确认偏离,打回" → Daemon 改状态回 pending
  - "方向扩展合理,批准继续" → 继续
  - "需要用户判断" → 通知用户
```

**设计推导**:
- OpenAI Agent SDK:Guardrail 本身是轻量 AI Agent(并行运行,专门做检查),不是 if-else 规则
- GSD must_haves truths:面向可观测行为,不是实现步骤
- v1.0 M4 Guard:entry/exit guard + skill 化检查逻辑,方向正确但绑定在 DAG 节点上

**Scope Guard(异步检查,不阻塞 Agent 执行)**:
- 触发时机:Agent claim 任务后在工作过程中写 decisions(scope 相关)时
- 检查方式:L2 sub 异步对比 scope_declaration vs task.truths
- 不阻塞:Agent 写完 scope_declaration 后继续工作,不等 Guard 结果
- 发现问题:写 observation(severity=warning),Daemon 下次 tick 触发庞统判断
- 兜底:即使 Scope Guard 漏报,庞统在 review 阶段仍会检查方向正确性

---

## 5. Agent 与黑板的交互

### 5.1 Agent 被_spawn_后的工作流程

```
Agent 被 spawn
    ↓
1. 读黑板 → 了解任务全局状态
   - 读 tasks 表:当前任务的状态、描述、依赖
   - 读 comments 表:讨论历史
   - 读 outputs 表:已有产出
   - 读 observations 表:已知风险
    ↓
2. 想 → 根据自己的职责自主决策
   - 我是编码先锋,这个 pending 任务适合我 → claim
   - 我是风控守将,这个 comment @ 我 → 回复
   - 我是副军师,这个任务需要分解 → 创建子任务
   - Agent claim 任务后、开始工作前,写 scope_declaration 到 decisions 表:
     "我计划做什么,产出什么"
     Scope Guard(L2 sub)会对比 scope_declaration vs task.truths
    ↓
3. 做 → 执行任务
   - 编码、审核、数据分析等
   - 过程中发现风险 → 写 observation
   - 需要其他人协助 → 写 comment @mention
    ↓
4. 写回黑板 → 产出、评论、状态更新、决策记录
   - 写 outputs 表:产出文件路径 + 摘要
   - 写 comments 表:完成说明
   - 写 decisions 表:关键决策(哪怕自己的决策也要填一条)
   - 更新 tasks 表:status → done/review
   - must_haves 三件套(任务创建时由庞统定义):
     - truths:用户视角的可观测行为("用户能看到回测结果"),不是实现步骤("编写回测脚本")
     - artifacts:必须存在的产出文件
     - constraints:继承的约束(如"不超过500行"、"必须用vnpy")
    ↓
5. 写 Handoff Comment → 退出
   - Agent 结束前必须写一条结构化的交接评论(借鉴 agent-chorus checkpoint)
   - 内容:完成什么、产出在哪、还剩什么、建议下一步
   - 这条 comment 会出现在下一个 Agent 的 L1 消息中(最近 3 条评论),实现无缝接手
   - 示例:
     ```
     blackboard.py comment --task task-001 --author zhangfei-dev \
       --body "## Handoff\n完成:分批加载实现\n产出:task-001/output-zhangfei-v2.md\n未完成:止损逻辑分批适配\n建议下一步:关羽 review 止损逻辑"
     ```
    ↓
6. Daemon 自动清理 session
   - 通知 Daemon(inbox JSONL)
   - Daemon 检测到完成 → 继续下一步(解锁下游 / spawn review / 清理 session)
```

**设计推导(Handoff Comment)**:
- agent-chorus 的核心机制是 Standup + Conclude:Agent 开始时读 inbox,结束时广播状态
- 映射到黑板:Standup = Agent spawn 后读黑板(L1),Conclude = Agent 结束时写 handoff comment
- agent-chorus 的 checkpoint 广播给所有其他 Agent → 我们的 handoff comment 通过 L1 自然传递给下一个 Agent
- 关键价值:**黑板上的状态足够让 Agent B 无缝接手 Agent A 的工作**--这正是 agent-chorus 解决的核心问题

### 5.2 Agent 工具集

Agent 通过 `exec` 工具调用 CLI 命令操作黑板:

```bash
# 读黑板(全部)
python3 ~/.sanguo_projects/sanguo_moziplus/cli/blackboard.py read --task task-001

# 读黑板(过滤:只读和自己相关的)
python3 ~/.sanguo_projects/sanguo_moziplus/cli/blackboard.py read --task task-001 --agent zhangfei-dev

# 读黑板(过滤:只读最近 20 条)
python3 ~/.sanguo_projects/sanguo_moziplus/cli/blackboard.py read --task task-001 --last 20

# 读黑板(过滤:只读特定类型)
python3 ~/.sanguo_projects/sanguo_moziplus/cli/blackboard.py read --task task-001 --type comments

# 认领任务
python3 ~/.sanguo_projects/sanguo_moziplus/cli/blackboard.py claim --task task-001 --agent zhangfei-dev

# 写产出
python3 ~/.sanguo_projects/sanguo_moziplus/cli/blackboard.py output --task task-001 --agent zhangfei-dev \
  --type code --title "分批加载实现" --path task-001/output-zhangfei.md \
  --summary "实现分批加载,单批50万条"

# 写评论
python3 ~/.sanguo_projects/sanguo_moziplus/cli/blackboard.py comment --task task-001 --author zhangfei-dev \
  --body "完成分批加载实现" --mentions "[]"

# 写观察
python3 ~/.sanguo_projects/sanguo_moziplus/cli/blackboard.py observe --task task-001 --observer guanyu-dev \
  --severity warning --body "止损逻辑需适配分批模式"

# 记录决策
python3 ~/.sanguo_projects/sanguo_moziplus/cli/blackboard.py decide --task task-001 --decider zhangfei-dev \
  --decision "使用分批加载而非流式" --rationale "流式需要改底层框架,分批只需改回测模块"

# 创建任务(任何 Agent 都可以创建)
python3 ~/.sanguo_projects/sanguo_moziplus/cli/blackboard.py create --title "分钟线数据下载" \
  --creator zhaoyun-data --task-type data

# 写 Handoff Comment（结构化，CLI 校验 Schema）
python3 ~/.sanguo_projects/sanguo_moziplus/cli/blackboard.py comment --task task-001 --author zhangfei-dev \
  --handoff '{"completed": "分批加载实现", "artifacts": ["task-001/output.md"], "remaining": "止损逻辑分批适配"}'
# --handoff 使用 schemas/handoff.schema.json 校验
# 缺必填字段 → CLI 返回具体错误，如 "Handoff must include 'completed' field"
# 校验通过 → 自动格式化为结构化评论写入 comments 表
```

---

## 6. 关键场景流程

### 6.1 庞统规划 + Agent 领任务(事件驱动版)

```
用户 → 庞统(主session):"设计一个动量因子策略"
    ↓
庞统在黑板上写:
  - 创建 task-001(数据准备,pending,无依赖)
  - 创建 task-002(因子计算,pending,depends_on: [task-001])
  - 创建 task-003(回测验证,pending,depends_on: [task-002])
  - 评论:"建议赵云领 001,张飞领 002 和 003"
    ↓
庞统写 inbox 通知: task_created
    ↓
Daemon Tick 发现 task-001 pending + 庞统评论建议赵云
  → spawn 赵云(L1 消息含任务核心 + 庞统建议)
    ↓
赵云读黑板 → claim task-001 → 执行 → 写产出
  → 写 Handoff Comment: "完成:分钟线数据下载 | 产出:task-001/data/ | 无未完成事项"
  → 更新 status→done → 通知 Daemon(inbox JSONL)
    ↓
Daemon ~1s 内收到 inbox 通知 → mini-tick:
  → 查询 depends_on 包含 task-001 的 pending 任务 → task-002
  → task-002 的依赖全部满足 → spawn 张飞(L1 消息含赵云的 handoff 摘要)
    ↓
(同理 task-002 done → 即时触发 task-003)
```

**对比 polling 版**:task-001 done 到 task-002 spawn 的延迟从 ≤60s 降到 ≤1s。张飞的 L1 消息中包含赵云的 Handoff Comment,无需额外查询即可无缝接手。

### 6.2 Agent 间协作讨论(事件驱动版)

```
张飞执行 task-002 时发现需要分钟线数据
    ↓
张飞写评论:"@赵云 task-002 需要分钟线数据,能帮忙下载吗?"
张飞更新任务状态 → blocked
  → 通知 Daemon(inbox JSONL)
    ↓
Daemon ~1s 内收到 inbox 通知 → mini-tick:
  → 解析 @mention → 赵云
  → spawn 赵云(L1 消息含评论摘要)
    ↓
赵云读黑板 → 看到评论 → 下载数据 → 写产出
赵云写评论:"@张飞 数据就绪,可以继续" + 写产出
  → 通知 Daemon(inbox JSONL)
    ↓
Daemon 收到通知 → @mention → spawn 张飞
    ↓
张飞读黑板 → 看到数据就绪 → 继续 task-002
```

**对比 polling 版**:@mention 响应从 ≤60s 降到 ≤1s。

### 6.3 Agent 发现风险

```
张飞在 task-002 中发现止损逻辑有 bug
    ↓
张飞写 observation(severity: warning):
  "止损逻辑在分批模式下可能漏触发"
张飞写评论:"@关羽 止损逻辑需要你从风控角度确认"
    ↓
Daemon tick 发现 observation + 评论 @ 关羽
    ↓
Daemon spawn 关羽 → 关羽读黑板 → 审查 → 写评论 + observation
```

### 6.4 用户直接参与

```
用户读黑板 → 发现 task-002 进度慢
    ↓
用户在黑板上写评论:"task-002 优先级提高,需要今天完成"
    ↓
Daemon tick 发现用户评论 → 如果张飞未 active → spawn 张飞通知
```

---

## 7. Session 隔离与清理

### 7.1 技术实现

```python
class SessionManager:
    def async_spawn_agent(self, agent_id: str, message: str) -> str:
        """异步 spawn 隔离 session,不等待完成。返回 session_id。"""
        session_id = str(uuid.uuid4())
        cmd = [
            "openclaw", "agent",
            "--agent", agent_id,
            "--session-id", session_id,
            "--message", message,
            "--json"
        ]
        # Popen 异步启动,不阻塞 daemon tick
        subprocess.Popen(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
        log_event(agent=agent_id, event_type='agent_spawned', detail={'session_id': session_id})
        return session_id

    def cleanup_session(self, agent_id: str, session_id: str, archive_dir: str):
        """存档 jsonl + 文件锁保护下清理 sessions.json"""
        sessions_dir = f"/Users/chufeng/.openclaw/agents/{agent_id}/sessions"
        store_path = f"{sessions_dir}/sessions.json"
        lock_path = f"{sessions_dir}/.cleanup.lock"

        # 1. 存档 jsonl 文件
        os.makedirs(archive_dir, exist_ok=True)
        for ext in ['.jsonl', '.trajectory.jsonl', '.trajectory-path.json']:
            src = f"{sessions_dir}/{session_id}{ext}"
            if os.path.exists(src):
                shutil.move(src, f"{archive_dir}/{session_id}{ext}")

        # 2. 文件锁保护下编辑 sessions.json(防止和 Gateway 并发写入冲突)
        with open(lock_path, 'w') as lock_file:
            fcntl.flock(lock_file, fcntl.LOCK_EX)
            try:
                with open(store_path) as f:
                    store = json.load(f)

                keys_to_remove = [k for k in store if session_id in k]
                for k in keys_to_remove:
                    del store[k]

                with open(store_path, 'w') as f:
                    json.dump(store, f, indent=2)
            finally:
                fcntl.flock(lock_file, fcntl.LOCK_UN)
                os.unlink(lock_path)
```

### 7.2 验证结论

| 验证项 | 结果 |
|--------|------|
| `openclaw agent --session-id <uuid>` 创建隔离 session | ✅ 通过 |
| 连续 spawn 多个 session 互不干扰 | ✅ 通过 |
| 并行 spawn 成功 | ✅ 通过 |
| 直接编辑 sessions.json 删除记录安全 | ✅ 通过 |
| jsonl 存档后从原目录删除 | ✅ 通过 |
| Gateway WS sessions.delete(需 admin scope) | ❌ 不可用 |
| `openclaw sessions cleanup --fix-missing --enforce` | ❌ 对 agent main session 报错 |
| Agent 主 session 对 CLI spawn 的 sub 完全无感 | ✅ 确认(设计如此)|

---

## 8. Sanguo Mail:退役

v2.6 中 Mail 完全退役。黑板的两个操作替代了 Mail 的所有功能:

| Mail 功能 | 黑板替代 |
|----------|--------|
| 庞统分配任务 | 庞统在黑板创建 task + 评论 @指定 agent |
| Agent 间通信 | 评论 @mention |
| 结果回传 | 产出写入 outputs 表 + 评论通知 |
| 讨论 | 评论线程 |

黑板比 Mail 更可靠:信息集中在 SQLite(不分散在 mail 目录)、有状态追踪、评论线程保持上下文完整、SQLite 读写比 Mail poller 更可靠。

如果需要系统级通知(daemon 异常、Gateway 状态),在黑板上创建 `system` 类型任务处理。

---

## 9. 质量门控(挑战/评审体系)

### 9.1 设计目标

课题1定义了"谁来判断"（双轨制）和"判断什么"（must_haves三件套、Guardrail吹哨人）。课题3解决"判断结果怎么记录、怎么协商、怎么流转"。

v1.0 三层体系（PAV自律 → 司马懿review → 庞统+司马懿终审）的问题：
1. PAV 形同虚设——Skill是"菜单"不是"触发器"，Agent可忽略
2. 每个节点都审过重——没有分级，简单/复杂任务同一个审查标准
3. 方案阶段没审查——只审产出不审方案
4. 评审结果不结构化——自然语言评论，无法机器判断
5. 司马懿角色重叠——节点审一次+终审一次

### 9.2 分级审查流水线

> **参考实践**：superpowers 串行双审、TradingAgents 对抗辩论、v1.0 PRD 三层体系

| 任务风险等级 | 流水线 | 方案审查 | 产出审查 | 审查模式 | 最大轮次 |
|------------|--------|---------|---------|---------|---------|
| **high**（部署/策略/资金） | 三阶段 | ✅ 独立审查 | ✅ 独立审查 + Guardrail | 对抗辩论 | 5 |
| **standard**（编码/设计） | 二阶段 | ✅ 方案过挑战 | ✅ 产出过挑战 | 单审 | 3 |
| **low**（文档/格式化/搬运） | 一阶段 | ❌ 跳过 | ⚡ Guardrail 自动检查 | 自动 | 0 |
| **research**（调研/分析） | 一阶段 | ❌ 跳过 | ✅ 庞统确认方向 | 单审 | 2 |

**风险等级**:庞统创建任务时标注。默认 `standard`。task_type 为 `strategy`/`deploy` 自动设 `high`，`research` 自动设 `research`。

### 9.3 三阶段审查流程

> **参考实践**：superpowers（implementer → spec reviewer → code quality reviewer串行）、TradingAgents（Bull vs Bear辩论）

**阶段 1：方案审查（Plan Review）**——high/standard 任务

```
执行者提交 scope_declaration 到黑板 decisions 表
    ↓
挑战者审查方案
    ├── high：对抗辩论（正方 vs 反方 → 庞统裁决）
    └── standard：单审（指定挑战者，默认司马懿）
    ↓
通过 → 进入执行
未通过 → 协商修改（max_rounds 轮）
    └── 超轮次 → 升级用户
```

方案审查 vs Scope Guard（课题1）：
- Scope Guard 是过程中的软检查（L2 sub 异步，发现问题写 observation）
- 方案审查是正式评审（L3 Agent 审查，通过/打回有 verdict）

**阶段 2：执行 + Guardrail 自动检查**——所有任务

```
执行者按方案执行
    ↓
每次写 output 时 Daemon 自动触发 Guardrail
    ├── L1 机械检查（文件存在/JSON格式/字段非空）→ 不通过直接打回
    ├── L2 轻量 AI 检查（Schema校验/artifacts路径验证）→ 不通过写 observation
    └── L3 安全红线（tripwire：如直接操作生产环境）→ 立即中断
    ↓
Guardrail 通过 → 进入产出审查
```

**阶段 3：产出审查（Output Review）**——high/standard 任务

```
执行者提交产出到黑板 outputs 表
    ↓
挑战者审查产出（质量/完整性/与方案一致性）
    ↓
评审结果结构化记录到 reviews 表
    ↓
通过 → status: review → done
未通过 → status: review → working（打回重做）
    └── 协商在 comments 表
    └── 超轮次 → 升级用户
```

### 9.4 审查协议注册表（Review Protocol Registry）

> **参考实践**：
> - **superpowers**：三个独立 prompt 文件（implementer/spec-reviewer/code-quality-reviewer），每个角色有专属模板
> - **oh-my-claudecode Critic**：Investigation Protocol 分 Phase（预判→验证→多视角→缺口分析→自审），不同 artifact type 自动切换视角
> - **superpowers spec-reviewer**：prompt 注入对抗性指令（"DO NOT trust the report. Read the actual code."）

**问题**：审查者容易陷入局部审查（编码规范/编译通过），漏掉本质问题（需求一致性/语义正确性）。被挑战后一律照改不加思考。

**方案**：审查协议是代码注入的，不是靠 Agent 自己找 Skill。Daemon spawn 审查者时动态加载协议模板。

```
review_protocols/
├── plan_review.yaml          # 方案审查协议
├── output_review.yaml        # 产出审查协议
├── guardrail_l2.yaml         # L2 轻量AI检查协议
└── analysis_review.yaml      # 分析/调研审查协议
```

每个协议定义四个维度：

| 维度 | 内容 | 参考 |
|------|------|------|
| 审查维度（审什么） | dimensions 列表，每个有 weight（critical/major/minor）和 method | superpowers 三种 reviewer 各自的关注点 |
| 审查方法（怎么审） | investigation_protocol 分阶段执行 | oh-my-claudecode Critic 五阶段 Protocol |
| 多视角 | 按 artifact type 切换视角集 | Critic 代码视角（安全/新人/运维） vs 方案视角（执行者/利益相关者/怀疑论者） |
| 对抗性指令 | adversarial_instructions 防止走过场 | superpowers spec-reviewer "DO NOT trust" 指令 |

**Investigation Protocol 通用模式**（参考 Critic，各协议按场景裁剪）：

```
Phase 1 预判（Pre-commitment）：先不读产出，凭领域经验预测3-5个最可能出问题的点
Phase 2 验证（Verification）：读实际产出（不是报告），逐条验证
Phase 3 多视角（Multi-perspective）：从不同角色看产出
Phase 4 缺口分析（Gap Analysis）：不只看"什么有问题"，还看"什么缺失了"
Phase 5 自审（Self-audit）：给每个 finding 打 confidence，低 confidence 降级
```

**多视角矩阵**：

| 审查类型 | 多视角集合 |
|---------|----------|
| output_review（代码） | 安全 / 新人 / 运维 |
| plan_review（方案） | 执行者 / 利益相关者 / 怀疑论者 |
| analysis_review（调研） | 领域专家 / 实践者 / 反方辩手 |
| guardrail_l2（轻量） | 无多视角 |

### 9.5 反驳权（Rebuttal Phase）

> **参考实践**：TradingAgents Bull vs Bear 模式——双方都有表达权

审查不是单向的。但不是每次都触发反驳——有跳过条件：

**跳过条件**（不需 spawn 反驳）：
- 审查者 verdict=approved → 直接 done，跳过 rebuttal
- 审查者 verdict=needs_revision，但 issues 全是 minor severity → 执行者自然在 comments 接受并修改，不 spawn 反驳

**触发条件**（spawn 反驳）：
- 审查者 verdict=needs_revision，且 issues 中有 critical 或 major severity → spawn 原执行者反驳
- 审查者 verdict=rejected → spawn 原执行者反驳

```
审查者提交 review
    ↓
verdict=approved → 直接 done（跳过 rebuttal）
verdict=needs_revision 且只有 minor → 执行者直接修改（跳过 rebuttal）
verdict=needs_revision 且有 critical/major → spawn 反驳
    ↓
Daemon spawn 原执行者，注入反驳指令：
    "对每个 issue，明确表态：ACCEPT / REJECT / PARTIAL
     不允许全部接受不加思考。"
    ↓
执行者 response 写入 comments 表
    ↓
有 REJECT → Daemon spawn 审查者看 response → 继续协商
全部 ACCEPT → 修改后重提交 → 审查者 re-review
```

### 9.6 评审结果结构化存储（reviews 表）

> **参考实践**：
> - **Hermes**：Comment 的 metadata JSON 承载结构化数据
> - **SWE-agent**：Trajectory 线性追加，不修改历史
> - **GitHub PR Review**：APPROVE / REQUEST_CHANGES / COMMENT 三种 verdict

**设计原则**：追加写入不修改历史（SWE-agent），黑板索引+文件详情（课题2），结构化 verdict（GitHub PR Review）。

```sql
CREATE TABLE IF NOT EXISTS reviews (
    id TEXT PRIMARY KEY,
    task_id TEXT NOT NULL,
    output_id TEXT,
    reviewer TEXT NOT NULL,              -- agent id 或 'system'
    review_type TEXT NOT NULL,
    CHECK (review_type IN ('plan_review', 'output_review', 'guardrail', 'final_review')),
    verdict TEXT NOT NULL,
    CHECK (verdict IN ('approved', 'rejected', 'needs_revision')),
    confidence REAL,                     -- 0.0-1.0
    round INTEGER NOT NULL DEFAULT 1,
    max_rounds INTEGER NOT NULL DEFAULT 3,
    consensus_reached BOOLEAN DEFAULT FALSE,
    summary TEXT NOT NULL,               -- 一句话结论（黑板索引）
    detail_path TEXT,                    -- 完整评审报告文件
    created_at TEXT NOT NULL DEFAULT (datetime('now')),
    FOREIGN KEY (task_id) REFERENCES tasks(id),
    FOREIGN KEY (output_id) REFERENCES outputs(id)
);

CREATE INDEX IF NOT EXISTS idx_reviews_task ON reviews(task_id);
CREATE INDEX IF NOT EXISTS idx_reviews_output ON reviews(output_id);
```

**Guardrail 检查结果也入 reviews 表**（`reviewer='system'`, `review_type='guardrail'`）。

**comments 表和 reviews 表职责分离**：

| 表 | 职责 | 内容 | verdict |
|---|------|------|---------|
| comments | 讨论、@mention、协商过程 | 自然语言 | ❌ 无 |
| reviews | 正式评审结论 | 结构化 JSON | ✅ 必须有 |

### 9.7 协商流程与状态机对齐（v2.8 更新）

**现有状态机（v2.8，11个状态）**：`pending → claimed → working → review → done`

| 状态转换 | 触发条件 | 对应阶段 |
|---------|---------|--------|
| working → working | 方案审查 needs_revision | 阶段 1 |
| working → review | 写 output + Guardrail 通过 | 阶段 2→3 |
| working → working | Guardrail rejected（自动打回） | 阶段 2 |
| working → escalated | Agent 遇到无法处理的问题 | 任意阶段 |
| working → waiting_human | Agent 触发 Checkpoint | 任意阶段 |
| review → done | 产出审查 approved | 阶段 3 |
| review → working | 产出审查 needs_revision | 阶段 3 |
| review → escalated | 超轮次升级用户 | 阶段 3 |
| review → waiting_human | 审查阶段需人工裁定 | 阶段 3 |
| waiting_human → working | Checkpoint reject（驳回） | 阶段 3 |
| waiting_human → done | verify Checkpoint approve（通过） | 阶段 3 |

**v2.8 变更**: `escalated` 从布尔标志改为独立状态（`status="escalated"`），不再使用 `review + escalated flag` 模式。超轮次时直接进入 `escalated` 状态，通知用户裁定。用户裁定后恢复到 `working` 或 `pending`。


low 风险任务：working → [Guardrail 自动检查] → done（跳过 review 状态）
research 任务：working → [庞统确认] → review → done

### 9.8 声明式 Guardrail 配置

> **参考实践**：OpenAI Agent SDK `@output_guardrail` 装饰器、v1.0 M4 Guard、SonarQube rule_id 模式

```yaml
# guardrails.yaml
#
# L1 check 用 assert 字段（Python 表达式，Daemon eval 执行）
# L2 check 用 prompt 字段（传给 subagent 的检查指令）
# 两者本质不同，不用同一个字段

task_types:
  coding:
    output_guardrails:
      - name: file_exists
        assert: "len(output.get('files', [])) > 0"
        severity: blocking
        layer: L1
      - name: json_valid
        assert: "output.get('json_schema_valid', False) == True"
        severity: blocking
        layer: L1
      - name: artifacts_exist
        assert: "all(os.path.exists(p) for p in output.get('artifacts_paths', []))"
        severity: blocking
        layer: L1
      - name: scope_alignment
        prompt: "Compare the agent's scope_declaration against task truths. Check: is every truth covered? Are there deviations not declared?"
        severity: warning
        layer: L2
    output_review:
      required: true
      mode: single_reviewer
      max_rounds: 3

  deploy:
    plan_review:
      required: true
      mode: debate
      max_rounds: 5
    output_guardrails:
      - name: no_direct_production
        assert: "output.get('target_env') != 'production'"
        severity: tripwire
        layer: L1
      - name: rollback_plan_exists
        assert: "output.get('rollback_plan') is not None"
        severity: blocking
        layer: L1
    output_review:
      required: true
      mode: debate
      max_rounds: 5

  data:
    output_guardrails:
      - name: format_check
        assert: "output.get('format') in ['csv', 'parquet', 'json']"
        severity: blocking
        layer: L1
    output_review:
      required: false

  research:
    output_review:
      required: true
      reviewer: "pangtong-fujunshi"
      mode: single_reviewer
      max_rounds: 2
```

### 9.9 Full Agent vs Subagent vs Daemon 直接执行

> **参考实践**：
> - **superpowers**：Implementer/Spec Reviewer/Code Quality Reviewer 都是 Task tool dispatch 的 subagent，各自独立 prompt 和模型
> - **oh-my-claudecode**：Critic 被禁止 Write/Edit 工具（disallowedTools），角色隔离
> - **open-multi-agent**：TaskQueue 维护 agent pool，scheduler 按 capability-match 分配

**判据**：

| 问题 | Full Agent | Subagent | Daemon 直接执行 |
|------|-----------|---------|----------------|
| 需要独立身份/人格？ | ✅ | ❌ | ❌ |
| 需要 Agent 专属工具？ | ✅ | ❌ 通用工具 | 不需要 AI |
| 任务复杂度 | 编码/审查/调研/决策 | 单一检查/快速评估 | 格式校验/文件检查 |
| 需要写黑板？ | ✅ | ❌ 只返回 pass/fail | 只改状态 |
| 需要多轮交互？ | ✅ | ❌ 一次性 | 一次性 |

**场景映射**：

| 场景 | 方式 | OpenClaw API | 理由 |
|------|------|-------------|------|
| 执行者编码/数据/部署 | Full Agent | `openclaw agent --agent <id>` | 需要身份+专属工具 |
| 挑战者审查 | Full Agent | `openclaw agent --agent simayi-challenger` | 需要质量守门人角色+多轮 |
| 执行者反驳 | Full Agent（原 Agent） | `openclaw agent --agent <原执行者>` | 需要原执行者身份 |
| 庞统规划/裁决 | Full Agent（隔离session） | `openclaw agent --agent pangtong-fujunshi --session-id <new>` | 避免主session上下文膨胀 |
| L2 Guardrail AI 检查 | Subagent | `sessions_spawn(task=...)` | 单一检查、无身份 |
| Scope Guard 异步检查 | Subagent | `sessions_spawn(task=...)` | 轻量一次性 |
| L1 机械校验 | 不走 AI | Daemon 直接执行 | 纯机械操作 |

**简化规则**：黑板上有名字的角色走 Full Agent。无名字的一次性检查走 Subagent。纯机械检查 Daemon 自己做。

**庞统主 session 隔离策略**：主 session 做轻量调度（L1构建、状态检查）。复杂的任务拆解和裁决 spawn 隔离 session，避免上下文膨胀。

### 9.10 对抗辩论模式（high 风险任务）

> **参考实践**：TradingAgents Bull vs Bear → Research Manager 裁决

```
正方（执行者）：scope_declaration，论证方案可行性
反方（挑战者池）：找方案漏洞、风险、遗漏
    ↓
庞统裁决：综合双方观点
    ├── 认可正方 → 方案通过
    ├── 认可反方 → 方案打回
    └── 综合意见 → 要求修改后重新辩论
```

**挑战者池**（按任务类型选择，不是固定司马懿）：

| 任务类型 | 默认挑战者 |
|---------|----------|
| 编码 | 司马懿 |
| 风控 | 关羽 |
| 数据 | 赵云（数据质量视角） |
| 部署 | 姜维 |

---

## 10. 产出物目录约定

```
~/.sanguo_projects/sanguo_moziplus/artifacts/
└── {task-id}/
    ├── outputs/          # Agent 产出物(代码、文档、数据)
    ├── archive/          # session jsonl 存档
    └── data/             # 数据文件
```

Agent 写产出时,`content_path` 指向此目录。Daemon 存档 session jsonl 时也写入 `archive/` 子目录。

---

## 11. 保留 v2.0 的设计

以下 v2.0 的设计在 v2.6 中保留:

1. **SQLite WAL 模式** - 黑板数据库同样使用 WAL
2. **结构化产出规范** - output.md frontmatter + 结论 JSON(写在黑板 outputs 表中)
3. **观察机制** - v2.0 Report Watcher 的思路升级为 observations 表
4. **证据原则** - 结论必须有证据(代码行号、日志、文件内容)
5. **审核流程** - 可通过黑板评论 + 状态机实现

---

## 11. 上下文管理策略（课题10结论）

> **核心结论**：不需要复杂的压缩/摘要机制。课题2+4的设计已覆盖上下文管理的主要场景。

### 11.1 黑板信息量测算

| 信息类型 | 单个任务估算 |
|---------|------------|
| 任务基础信息（tasks 表） | ~50-60 tokens |
| 10 条评论（comments 表） | ~300-500 tokens |
| 5 个产出摘要（outputs 表） | ~150-250 tokens |
| 10 条事件日志（events 表） | ~150-250 tokens |
| 3 条决策记录（decisions 表） | ~150-200 tokens |
| **单个任务全量** | **~1000-1500 tokens** |

即使 10 个任务全量注入也仅 ~1-1.5 万 tokens，远小于 128K context window。

### 11.2 三个场景的结论

**场景1：续杯时上下文膨胀**

已在课题2+4中解决：
- 黑板保留完整讨论链（comments/decisions/observations），新 Agent 随时可读
- 课题4 D4-7 三段式注入：操作规范 + 任务上下文 + 前序信息（depends_on 产出）
- 比 GSD Wave Execution 更优——GSD 给每个 executor 全新 context 但丢弃思考过程，我们保留在黑板中

**场景2：多任务并行**

所有优秀实践的共识：单黑板、单 Daemon、多任务并行调度。
- open-multi-agent：一个 TaskQueue，事件驱动，无依赖任务自然并行
- Hermes：一个 Dispatcher + 一个 SQLite，60s tick 扫描
- GSD：一个 orchestrator，同 wave 并行，跨 wave 串行

moziplus 同此模式：一个 SQLite 黑板、一个 Daemon 进程、Tick 扫描可推进的任务并行 spawn。
每个 Agent spawn 时只注入自己任务的信息（课题4 D4-7 按角色注入），不受其他任务干扰。

**⚠️ 待解决**：用户级多任务（跨项目/跨域）需要项目级隔离机制，与课题11一起设计。

**场景3：Agent 自主决定读 L3**

在 L2 bootstrap 末尾注入"可选参考"提示（课题4 D4-11 已在示例中体现）：
```
═══ 可选参考 ═══
根据任务需要，你可以用 read 加载以下 Skill：
- 编码：~/.openclaw/skills/coding-implementation/SKILL.md
- 回测：~/.openclaw/skills/quant-backtest/SKILL.md
只在需要时加载，不需要全部读取。
```

未来增强：SkillRouter 检索 + OpenClaw 动态关键词触发（见课题12 SkillRouter 调研）。

### 11.3 Context 预算分配

| 组件 | 预算 | 说明 |
|------|------|------|
| System Prompt + SOUL.md + IDENTITY.md | ~3000-5000 | 固定开销（L0+L1） |
| L2 引擎注入（操作规范 + 任务上下文） | ~1000-2000 | 每次 spawn 强制注入 |
| L2 历史经验提醒 | ~150 | 最多 3 条 experience |
| L3 可选参考 | ~100 | Skill 列表提示 |
| 工作空间（Agent 思考+输出） | ~30000-50000 | 预留给 Agent |
| **总计** | **~35K-60K** | 远小于 128K，安全 |

### 11.4 设计原则

1. 黑板是索引（做什么 + 在哪找），不是仓库（详细内容）
2. 产出物在文件中，黑板只存路径
3. Agent spawn 时传最小充分上下文（L2），按需获取更多（L3）
4. 不做复杂压缩——信息量本身就很小

---

## 12. 开发策略(v2.6)

> **核心原则：不分阶段，不妥协，直奔 AI Native。** 每个部分设计到清楚为止。

### 12.1 设计推进方式

按课题逐个推进。课题之间允许并行，不强求串行。每个课题设计清楚就定稿。

**已完成设计的课题**：
- ✅ 课题1：三层执行模型（v2.6.2）
- ✅ 课题2：事件驱动 + Inbox JSONL（v2.6.3）
- ✅ 课题3：挑战/评审体系（v2.6.4）
- ✅ 课题4：拆解 + 上下文架构（v2.6.5）
- ✅ 课题6：经验沉淀闭环（v2.6.7）
- ✅ 课题7+9：交互模式 + Dashboard（v2.6.6 → 方案文档 v2.6.11）
- ✅ 课题11：多项目支持（v2.6.10）

### 待推进课题

| 课题 | 内容 | 方向 | 状态 |
|------|------|------|------|
| 课题7 | AI Native 人机交互 | 4种交互模式+推送4级+信息3层+双入口对等+Checkpoint交互+AI Briefing | 📐 方案完成 |
| 课题9 | Dashboard 设计 | v1.0已有11个Tab全部保留，任务看板重设计，SSE实时推送，新增AI Briefing Tab | 📐 方案完成 |
| 课题10 | 上下文管理 | — | ⏸️ 暂缓 |
| 课题11 | 用户级多项目 | 方案C：单Daemon多数据库 + per-project线程并发 + 全局LLM信号量 + per-agent互斥锁（借鉴open-multi-agent AgentPool） | 📐 方案完成（v2） |
| 节点级模型策略 | Aider architect/editor/weak 三层分工 | 审查节点用强模型、执行节点用快模型，成本与质量平衡 | P2 |
| 信任分级系统 | DeepSeek-TUI Plan/Agent/YOLO 三级 | Dashboard 按信任等级展示不同操作按钮 | P2 |
| Worktree 项目隔离 | Superset + Claude Squad | 同项目内多Agent并行改代码的物理隔离 | P1 |
| Blackboard Map | Aider Repo Map | 黑板结构化索引，Agent按任务ID只读关联子图，不全量读取 | P3（触发条件：单任务>5K tokens 或并行>15任务） |
| 工具链集成 | PRD C10 | DevOps工具链（代码管理/CI/CD/测试/沙箱/运维）集成到v2.0 | 📋 信息收集（`docs/design/toolchain-proposal.md`） |

### 司马懿 v2.6.9 评审结论与回应

**评分**: 55/70。最高：上下文管理 9/10。最低：自主协作能力 + 异常自愈 7/10。

**3 个评审意见的回应**：

| # | 司马懿意见 | 回应 | 处理 |
|---|-----------|------|------|
| 1 | PRD §2.1 B3"共享意识"与架构有差距，改PRD对齐 | PRD 目标正确不改。当前架构已基本实现共享意识（黑板+CLI读写+@mention+Handoff），唯一差距是 L2 prompt 需要告诉 Agent"你可以查全局" | 在 §15.1 借鉴4 的 prompt_template 中加入全局查询提示 |
| 2 | blocked 状态转换图不完整 + mentions/experience_tags 风格不统一 | blocked 定义完整（§3.3 转换矩阵含 blocked，§6.2 场景清晰：Agent执行中被卡→blocked→他人帮忙→pending）。mentions 做通知路由（轻查询），experience_tags 做统计分析（重查询），场景不同不需要统一格式 | 不修改 |
| 3 | verification_commands 安全性 | Agent 已有 exec 权限，verification_commands 走 Daemon exec，由 OpenClaw exec approvals 机制（allowlist+approval）保障安全，不引入新攻击面。参考：Claude Code 同模型、Aider 直接信任、NVIDIA 深度防御指南 | 在 §15.1 借鉴1 明确安全模型 |

**采纳的改进建议**：
- ✅ Daemon 逻辑健康自检（连续 N tick 无变更则告警）→ 纳入 §14 风险缓解
- ✅ PRD 与架构对齐描述 → 在架构文档中记录当前状态而非修改 PRD
- 📋 多项目 scope → 课题11 设计
- 📋 AI Retry 基本版 → Phase 1 考虑
- 📋 SkillRouter → 课题12

### 已完成调研

- ✅ 7 个新项目调研（Claude Squad / Superset Terminal / OpenCode / claude-goal / Cline / Aider / DeepSeek-TUI）
  - 综合报告：`docs/research/research-seven-projects-synthesis.md`
  - 详细报告：`docs/research/research-batch{1,2,3}-*.md`

### 12.2 开发启动条件

所有核心课题设计完成后启动开发。开发顺序由设计依赖关系决定，不由阶段划分决定。

### 12.3 核心依赖链（设计 → 开发）

```
黑板基础设施（SQLite + CLI + Daemon）
  → 事件驱动（Inbox + 依赖推进）
    → Agent 交互（Handoff + 评论 + Observation）
      → 审查体系（Review + Guardrail + 反驳）
        → 智能化（AI规划 + 自主领活 + 经验沉淀）
          → Dashboard 前端
```

每层依赖前一层，但不等所有层设计完才开发。前层设计清楚即可开发。

---

## 13. 技术选型

| 需求 | 参考系统 | 我们的方案 | 理由 |
|------|---------|-----------|------|
| 共享状态 | Hermes SQLite + Network-AI flock | SQLite WAL + 事务 CAS | 原子性 + 无外部依赖 |
| 讨论 | Hermes kanban_comment | comments 表 + @mention | 简单追加写入,所有人可见 |
| 事件驱动 | open-multi-agent EventEmitter + agent-chorus JSONL inbox | Tick 核心 + Inbox JSONL 加速 + 启动全量扫描 | Tick 兜底可靠,inbox 加速即时响应,零新依赖 |
| 调度 | Hermes Dispatcher 60s tick | Tick 30s + Inbox JSONL 加速 + 启动全量扫描 | Tick 可靠 + inbox 即时 |
| 上下文传递 | GSD Wave Execution + Claude Code file ref + Opal-Bridge Fidelity | L1 必传 + L2/L3 按需读取 + Handoff Comment | 信号噪声比优化 + 无缝接手 |
| 通知 | Claude Code idle notification | Daemon spawn + L1 message | OpenClaw 原生能力 |
| 通信 | Hermes kanban_comment + Claude Code inbox | 黑板 comments + @mention | 替代 Sanguo Mail |
| 竞态 | Network-AI propose→validate→commit | SQLite CAS(first-commit-wins) | SQLite 事务足够 |
| Session | Hermes process-per-worker | openclaw agent --session-id | OpenClaw 原生隔离 |
| 清理 | 无参考 | 编辑 sessions.json | 已验证可行 |

---

## 14. 风险和缓解

| 风险 | 概率 | 缓解 |
|------|------|------|
| Agent 上下文不足(隔离 session 没有历史)| 中 | spawn 时传递黑板关键信息 + agent 可主动读黑板 |
| Daemon 单点故障 | 低 | PM2 自动重启 + tick 无状态 |
| SQLite 并发写入 | 中 | WAL + busy_timeout + BEGIN IMMEDIATE |
| 黑板膨胀(大量评论/产出)| 低 | 定期 archive + agent 只读最近 N 条 |
| Agent 不知道该做什么 | 中 | Skill 指导 + 庞统 plan 评论 + daemon 消息含上下文 |
| Sanguo Mail 退役后的系统通知 | 低 | 黑板 system 类型任务替代 |
| Daemon 逻辑死循环 | 中 | Daemon 逻辑健康自检：连续 N tick（默认 20）无任何任务状态变更则写 observation 告警 + 通知用户。PM2 只能检测进程崩溃，逻辑死循环需应用层检测 |

---

## 15. 7项目调研结论与设计借鉴

> **调研日期**: 2026-05-16
> **调研范围**: Claude Squad / Superset Terminal / OpenCode / claude-goal / Cline / Aider / DeepSeek-TUI
> **详细报告**: `docs/research/research-seven-projects-synthesis.md`

### 15.1 已纳入设计的借鉴点

#### 借鉴1：Guardrail 验证脚本层（纳入课题3）

**来源**: Aider lint→test→commit 质量闭环

**当前设计**（topic3 方案 阶段2）：
```
L1 机械检查（文件存在、JSON格式）→ 不通过直接打回
L2 轻量 AI 检查（Schema校验）→ 不通过写 observation
L3 安全红线（tripwire）→ 立即中断
```

**增强后**：L1 增加验证脚本层
```
L1 机械检查 + 验证脚本
  ├── 文件存在性检查（原有）
  ├── JSON 格式检查（原有）
  └── 🆕 verification_commands 执行（新增）
      ├── 任务 Plan 中声明的验证命令（如 pytest, flake8, mypy）
      ├── 命令 exit 0 = 通过，非 0 = 打回
      └── stdout/stderr 附在打回原因中
```

**黑板 Schema 变更**：tasks 表新增 `verification_commands` JSON 字段
```json
{
  "verification_commands": [
    {"cmd": "pytest tests/test_foo.py -x", "description": "单元测试必须通过"},
    {"cmd": "flake8 src/", "description": "代码规范检查"}
  ]
}
```

**触发时机**：Daemon 检测到 output 写入 → 执行 Guardrail → L1 验证脚本 → 脚本失败则自动打回。

**安全模型**：verification_commands 通过 Daemon 调用 `exec`，走 OpenClaw exec approvals 机制（allowlist + approval）。Agent 已有 exec 权限，verification_commands 不引入新的攻击面。参考：Claude Code 同模型（Agent 可执行命令，宿主机 exec approvals 拦截危险操作）、Aider 直接信任、NVIDIA 深度防御指南。

> 参考实践：Aider 的 lint→test→commit 是原子操作——验证不通过就不 commit。我们的 Guardrail 也是原子门控——验证不通过就不进入 review。

#### 借鉴2：对抗性审计映射（纳入课题3）

**来源**: claude-goal 三种审计模式（none/adversarial/double）

**映射到 Guardrail L1/L2/L3**：

| claude-goal 模式 | moziplus Guardrail | 触发条件 | 行为 |
|-----------------|-------------------|---------|------|
| none（跳过审计） | L1 only（机械+脚本） | low 风险任务 | 自动检查通过即完成 |
| adversarial（对抗审计） | L1 + L2（AI审查） | standard 风险任务 | 一轮 AI 审查，通过/打回 |
| double（双重审计） | L1 + L2 + 反驳权 | high 风险任务 | 双轮审查 + 执行者可反驳 + 最多5轮 |

> claude-goal 的完成审计 6 步流程（还原交付物→对照表→检查证据→找缺失→继续/完成）对 Output Guard 的 AI 审查层有参考价值，但不硬编码步骤——AI 审查者按 Skill 指导灵活执行。

#### 借鉴3：防偏离改进（纳入课题3+4）

**来源**: claude-goal Stop Hook + 完成审计

**v2.0 的防偏离三层防线**：

| 防线 | claude-goal 机制 | moziplus v2.0 对应 | 实现方式 |
|------|-----------------|-------------------|---------|
| 每轮重新注入目标 | Stop Hook 注入 `<objective>` | L2 引擎注入任务上下文 | Daemon spawn 时注入 truths + acceptance_criteria |
| 不信任 Agent 自述 | 完成审计 6 步（查证据） | Output Guard + Scope Guard | L1 验证脚本 + L2 AI 审查（prompt→artifact 对照） |
| Runaway Guard | 500 次续杯上限 | ❌ 当前缺失 | 新增：每个任务最大 tick 上限（配置项 `max_ticks`，默认 100） |

**新增设计**：tasks 表增加 `max_ticks` 字段（默认 100）。Daemon 每次 tick 处理某任务时递增 `tick_count`，超过 `max_ticks` 时：
1. 自动暂停任务
2. 写入 system observation：“任务超过最大 tick 上限，可能陷入循环”
3. 通知用户决定继续/取消

#### 借鉴4：双重 Hook 机制（纳入 Daemon 设计）

**来源**: claude-goal 的 Claude Code Stop Hook + mozi v1 的 HookRegistry

**v2.0 双重 Hook 架构**：

```
┌─────────────────────────────────────────┐
│ Layer 1: OpenClaw Hook（系统级）          │
│ • Heartbeat（定时轮询，读 HEARTBEAT.md） │
│ • Webhook（HTTP 入口，外部事件触发）      │
│ • Cron（定时任务）                        │
│ → 触发 Agent session 内行为              │
└─────────────────────────────────────────┘
         ↓ 事件到达
┌─────────────────────────────────────────┐
│ Layer 2: moziplus Hook（编排级）         │
│ • NODE_AFTER_EXECUTE → 触发 Guardrail    │
│ • NODE_ON_SUCCESS → 触发经验沉淀          │
│ • TASK_AFTER_COMPLETE → 触发 Scope Guard │
│ • CONCLUSION_AFTER_PARSE → 写入黑板      │
│ → 触发编排层业务逻辑                     │
└─────────────────────────────────────────┘
```

**mozi v1 已有 HookRegistry**（20 个 hook 点，覆盖任务/节点/结论/路由全生命周期），v2.0 继承并精简：
- v1 的 HookPoint 枚举 → v2 的 Daemon event handler
- v1 的 priority + stop_propagation → v2 保留（Hook 链可控）
- v1 的两级失败隔离（关键型暂停/辅助型跳过）→ v2 保留
- 新增：Guardrail 验证脚本作为 NODE_AFTER_EXECUTE 的默认 Hook

**与 claude-goal 的对比**：
| 维度 | claude-goal | moziplus v2.0 |
|------|-----------|-------------|
| Hook 注册位置 | Claude Code settings.json | Daemon HookRegistry |
| Hook 触发点 | Agent Stop 事件 | 节点完成/任务完成/产出写入 |
| Hook 实现 | Python 脚本 | Daemon event handler + 可插拔 Hook |
| 防偏离手段 | 拦截停止+注入目标 | L2注入上下文+Guardrail验证+Runaway Guard |

#### 借鉴5：Shadow Checkpoint（纳入课题6 经验沉淀）

**来源**: Cline Shadow Git Checkpoint

**设计**：每次 Agent 产出写入黑板时，Daemon 自动对产出目录做 git commit（带 agent_id + task_id + timestamp tag）。

- **与课题4的关系**：不依赖课题4。Shadow Checkpoint 是 Daemon 层行为（产出写入后触发），课题4是 Agent spawn 时的上下文注入。两者独立。
- **与课题6的关系**：Shadow Checkpoint 的变更历史是经验蒸馏的输入（课题6 DISCOVER 阶段可以 diff 两个 checkpoint 看Agent改了什么）
- **回滚能力**：用户可以在 Dashboard 上选择任意 checkpoint 一键回滚
- **存储开销**：git commit 增量存储，开销可控

**实现**：在 `NODE_AFTER_EXECUTE` Hook 中增加 git checkpoint 逻辑。

### 15.2 经评估暂不纳入的借鉴点

#### Blackboard Map（按需触发，不预设）

**来源**: Aider Repo Map

**结论**：当前单个任务黑板信息 ~1000-1500 tokens（§11.1 测算），10 个任务全量注入 ~1-1.5 万 tokens，远小于 128K。**现阶段不需要 Blackboard Map**。

**触发条件**（达到以下任一时启动设计）：
- 单个任务黑板信息超过 5000 tokens
- 并行任务数超过 15 个
- Agent spawn 时注入上下文超过 10K tokens
- 或者 L2 注入需要做精准裁剪（只取关联子图而非全量）

**预留设计**：当需要时，基于黑板 comments/outputs/decisions 的拓扑关系构建图索引，Agent 按任务 ID 只读关联子图。

### 15.3 技术选型更新

| 需求 | 原参考 | 新增参考 | 我们的方案 |
|------|--------|---------|----------|
| 质量门控 | Hermes 幻觉门控 | Aider lint→test→commit | L1 机械+脚本 → L2 AI → L3 红线 |
| 防偏离 | 无 | claude-goal Stop Hook + 完成审计 | L2 注入 + Guardrail + Runaway Guard |
| 产出追溯 | 无 | Cline Shadow Git | NODE_AFTER_EXECUTE Hook 自动 git commit |
| Hook 机制 | mozi v1 HookRegistry | claude-goal Stop Hook + OpenClaw Heartbeat/Webhook | 双重 Hook（系统级+编排级） |
| 多项目隔离 | 无 | Superset Worktree | 课题11 中设计（Worktree 物理隔离） |
