diff --git a/docs/design/deployment-v2.6.md b/docs/design/deployment-v2.6.md index 0f7be82..072985b 100644 --- a/docs/design/deployment-v2.6.md +++ b/docs/design/deployment-v2.6.md @@ -1,25 +1,31 @@ # v2.6 部署方案设计 -**版本**: v2.6.1-deploy (含评审修正 + 独立部署) -**基于**: technical-design-v2.6.md -**作者**: 庞统(副军师) -**日期**: 2026-05-15 +**版本**: v2.6.2-deploy +**基于**: technical-design-v2.6.md v2.6.2 +**作者**: 庞统(副军师)🐦 +**日期**: 2026-05-16 --- ## 1. 部署环境 -| 项目 | 当前状态 | -|------|---------| -| 主机 | 楚锋的 Mac mini (ARM64, macOS) | -| Python | 3.9.6(系统)+ 3.11(moziplus venv)| +| 项目 | 规格 | +|------|------| +| 主机 | 楚锋的 Mac mini (Apple M4, ARM64, 16GB RAM, macOS) | +| Python | 3.11(moziplus venv) | | Node.js | v22.22.1 | -| PM2 | 6.0.14(管理 10 个进程)| -| 运行目录 | `~/.sanguo_projects/sanguo_moziplus_v2/` | -| 开发目录 | `~/.openclaw/sanguo_projects/sanguo_moziplus_v2/` | -| Git 远程 | gitee (origin) + gitea (内网 NAS) | -| 前端 | port 8083(v2 独立端口) | -| Gateway | 127.0.0.1:18789 | +| PM2 | 6.0.14 | +| OpenClaw Gateway | 127.0.0.1:18789 | +| NAS | 192.168.2.154(SMB /Volumes/stock/) | +| Windows-Test-Node | 192.168.2.33 | + +### 目录规划 + +| 用途 | 路径 | 说明 | +|------|------|------| +| 开发目录 | `~/.openclaw/sanguo_projects/sanguo_moziplus_v2/` | Git 管理 | +| 安装目录 | `~/.sanguo_projects/sanguo_moziplus_v2/` | PM2 运行 | +| Git 远程 | gitee (origin) + gitea (NAS 192.168.2.154) | 双远程 | --- @@ -27,186 +33,363 @@ ``` PM2 (进程管理器) -├── sanguo-moziplus-v2 (port 8083) ← 🆕 v2 独立进程 -├── sanguo-moziplus (port 8082) ← v1 保留(v2 验证后下线) -├── sanguo-git-sync ← 不变 -├── sanguo-mail-* (8 个) ← 不变(v2 验证后下线) -└── sanguo-mozi ← 不变 +├── sanguo-moziplus-v2 (port 8083) ← 🆕 v2 主进程(API + Daemon ticker + 前端) +├── sanguo-moziplus (port 8082) ← v1 保留(v2 验证后下线) +├── sanguo-git-sync ← 不变 +├── sanguo-mail-* (8个) ← v2 验证后逐步下线 +└── sanguo-mozi ← 不变 -新增文件: +进程内部结构: +sanguo-moziplus-v2 +├── uvicorn (FastAPI) +│ ├── API 路由(黑板/Daemon/SSE/项目) +│ ├── 静态文件服务(frontend/dist/) +│ └── SSE 推送端点(/api/events) +├── asyncio background task: Daemon ticker(30s) +├── asyncio background task: Inbox watcher(1s 轮询) +└── ActiveAgentCounter(异步信号量) +``` + +**关键:v2 是单进程。** Daemon ticker 和 API 在同一个 asyncio event loop 中。不新增 PM2 进程。 + +--- + +## 3. 多项目数据布局 + +``` ~/.sanguo_projects/sanguo_moziplus_v2/ -├── blackboard.db ← 🆕 黑板数据库(自动创建) -├── artifacts/ ← 🆕 产出物目录(自动创建) -├── src/blackboard/ ← 🆕 黑板模块 -├── src/daemon/ ← 🆕 Daemon 模块 -├── src/api/ ← 🆕 API -├── src/cli/ ← 🆕 CLI -└── ecosystem.config.cjs ← 🆕 PM2 配置 +├── projects/ +│ ├── registry.db ← 全局注册表(项目列表+元数据) +│ ├── sanguo_quant_live/ +│ │ ├── blackboard.db ← per-project 黑板 +│ │ ├── config/ +│ │ │ └── project.yaml ← per-project 配置覆盖 +│ │ ├── artifacts/ ← per-project 产出物 +│ │ │ └── {task-id}/ +│ │ │ ├── outputs/ +│ │ │ ├── reviews/ +│ │ │ ├── archive/ +│ │ │ └── data/ +│ │ └── experiences/ ← per-project 经验库 +│ ├── sanguo_vnpy/ +│ │ └── ... +│ └── _archived/ ← 归档项目(只读) +│ └── old_project/ +│ +├── inbox/ +│ └── daemon.jsonl ← Inbox 事件推送 +│ +├── config/ +│ ├── default.yaml ← 全局默认配置 +│ ├── guardrails.yaml +│ ├── template_components.yaml +│ └── review_protocols/ +│ ├── plan_review.yaml +│ ├── output_review.yaml +│ ├── analysis_review.yaml +│ └── final_review.yaml +│ +├── prompt_templates/ ← L2 模板(全局共享) +├── schemas/ ← Schema 校验(全局共享) +└── src/ ← 代码 ``` -**关键:不新增 PM2 进程。** Daemon ticker 作为 asyncio background task 运行在 moziplus 进程内。 +**物理隔离**:每个项目的 blackboard.db 完全独立。一个项目数据库损坏不影响其他项目。 --- -## 3. 部署流程 +## 4. PM2 配置 -### 3.1 开发→安装同步 - -按照 AGENTS.md 的"代码变更标准流程",但简化(非代码变更,是文档确认后的首次实现): - -``` -步骤 1: 创建项目 - mkdir -p ~/.openclaw/sanguo_projects/sanguo_moziplus_v2 - cd ~/.openclaw/sanguo_projects/sanguo_moziplus_v2 - git init - git remote add origin git@gitee.com:cfdaily:sanguo_moziplus_v2.git - git remote add gitea http://192.168.2.154:3000/cfdaily/sanguo_moziplus_v2.git - -步骤 2: 开发编码 - ~/.openclaw/sanguo_projects/sanguo_moziplus_v2/src/blackboard/ - ~/.openclaw/sanguo_projects/sanguo_moziplus_v2/src/daemon/ - ~/.openclaw/sanguo_projects/sanguo_moziplus_v2/src/api/ - ~/.openclaw/sanguo_projects/sanguo_moziplus_v2/src/cli/ - -步骤 3: 单元测试通过 - cd ~/.openclaw/sanguo_projects/sanguo_moziplus_v2 - python3 -m pytest tests/unit/test_blackboard.py -v - python3 -m pytest tests/unit/test_daemon_tick.py -v - -步骤 4: 发司马懿评审(代码级) - -步骤 5: 评审通过后,同步到安装目录 - rsync -av --exclude='.venv' --exclude='node_modules' \ - ~/.openclaw/sanguo_projects/sanguo_moziplus_v2/ ~/.sanguo_projects/sanguo_moziplus_v2/ - -步骤 6: PM2 启动 v2 - cd ~/.sanguo_projects/sanguo_moziplus_v2 - pm2 start ecosystem.config.cjs - -步骤 7: 验证 - curl http://127.0.0.1:8083/api/daemon/status - python3 ~/.sanguo_projects/sanguo_moziplus_v2/src/cli/blackboard.py create --title "test" --creator test -``` - pm2 restart sanguo-moziplus - -步骤 6: 验证 - curl http://127.0.0.1:8082/api/daemon/status - python3 ~/.sanguo_projects/sanguo_moziplus_v2/src/cli/blackboard.py create --title "test" --creator test -``` - -### 3.2 数据库初始化 - -blackboard.db 在 moziplus 启动时自动创建和初始化(`init_blackboard_db()`)。不需要手动建表。 - -首次部署时 `blackboard.db` 文件不存在,启动后自动创建。后续启动检测到已存在则跳过 schema 初始化(`CREATE TABLE IF NOT EXISTS` 天然幂等)。 - ---- - -## 4. 回滚方案 - -| 场景 | 回滚方式 | -|------|---------| -| v2 启动失败 | `pm2 stop sanguo-moziplus-v2` → v1 不受影响 | -| Daemon tick 异常 | API 调用 `POST /api/daemon/stop` 停 ticker 不停服务 | -| SQLite 损坏 | 删除 `blackboard.db` 重启自动重建 | -| v2 整体不可用 | v1 仍在 8082 运行,切换回 v1 即可 | - -**关键:v1 和 v2 完全独立,互不影响。** v2 出问题直接停掉,v1 继续服务。 - ---- - -## 5. 监控 - -### 5.1 日志 - -所有黑板操作和 daemon tick 通过 Python logging 输出到 PM2 日志: - -```bash -# 查看 daemon tick 日志 -pm2 logs sanguo-moziplus --lines 100 | grep "Daemon\|Blackboard\|Tick" - -# 查看 spawn 日志 -pm2 logs sanguo-moziplus --lines 100 | grep "Spawning\|Cleaned up" -``` - -### 5.2 健康端点 - -``` -GET /api/daemon/status -返回: -{ - "ticker_running": true, - "last_tick": "2026-05-15T01:30:00", - "tick_interval_seconds": 60, - "active_sessions": 2, - "blackboard_db_size_bytes": 45056, - "tasks_summary": { - "pending": 3, - "claimed": 1, - "working": 2, - "review": 0, - "done": 15, - "failed": 1, - "blocked": 0 - } +```javascript +// ecosystem.config.cjs +module.exports = { + apps: [{ + name: 'sanguo-moziplus-v2', + script: '~/.sanguo_projects/sanguo_moziplus_v2/.venv/bin/uvicorn', + args: 'src.main:app --host 0.0.0.0 --port 8083', + cwd: '~/.sanguo_projects/sanguo_moziplus_v2', + interpreter: 'none', + autorestart: true, + max_restarts: 10, + restart_delay: 3000, + watch: false, + env: { + PYTHONPATH: '~/.sanguo_projects/sanguo_moziplus_v2', + BLACKBOARD_ROOT: '~/.sanguo_projects/sanguo_moziplus_v2/projects', + INBOX_PATH: '~/.sanguo_projects/sanguo_moziplus_v2/inbox/daemon.jsonl', + LOG_LEVEL: 'INFO', + }, + out_file: '~/.sanguo_projects/sanguo_moziplus_v2/logs/daemon.out.log', + error_file: '~/.sanguo_projects/sanguo_moziplus_v2/logs/daemon.err.log', + }] } ``` -### 5.3 PM2 告警 +--- -复用现有 PM2 配置,sanguo-moziplus 如果异常退出会自动重启(已配置 `max_restarts: 10`)。 +## 5. 配置体系 + +### 5.1 全局配置(default.yaml) + +```yaml +daemon: + tick_interval: 30 # Tick 间隔(秒) + task_timeout: 600 # 单任务超时(秒,10分钟) + max_global_agents: 5 # 全局最大并发 Agent + max_per_agent: 1 # 每 Agent 最大并发(默认 sequential) + zombie_threshold: 20 # 连续 N tick 无变更 → 告警 + +inbox: + path: "inbox/daemon.jsonl" + watch_interval: 1 # Inbox 轮询间隔(秒) + max_size_bytes: 1048576 # 1MB 触发 truncate + +review: + default_max_rounds: 3 + debate_max_rounds: 5 + confidence_threshold: 0.7 # 低于此值升级庞统 + +experience: + distill_threshold: 5 # 同 tag 积累 N 条触发二级蒸馏 + expire_days: 30 # 30天无引用 → deprecated + +logging: + level: INFO + max_file_size: 10MB +``` + +### 5.2 Per-project 配置覆盖 + +```yaml +# projects/{project_id}/config/project.yaml +project: + name: "量化实战项目" + description: "sanguo_quant_live" + agents: + - pangtong-fujunshi + - simayi-challenger + - zhangfei-dev + - guanyu-dev + - zhaoyun-data + - jiangwei-infra + max_global_agents: 3 # 覆盖全局默认 + context: + nas_path: "/Volumes/stock/" + backtest_service: "http://192.168.2.154:8088" + frameworks: + - "vnpy" + - "sanguo_vnpy" +``` --- -## 6. 安全考虑 +## 6. 部署流程 + +### 6.1 首次部署 + +```bash +# 1. 创建安装目录 +mkdir -p ~/.sanguo_projects/sanguo_moziplus_v2/{projects,inbox,logs,config} + +# 2. 同步代码(从开发目录) +rsync -av --exclude='.venv' --exclude='node_modules' --exclude='.git' \ + ~/.openclaw/sanguo_projects/sanguo_moziplus_v2/ \ + ~/.sanguo_projects/sanguo_moziplus_v2/ + +# 3. 安装 Python 依赖 +cd ~/.sanguo_projects/sanguo_moziplus_v2 +python3 -m venv .venv +.venv/bin/pip install fastapi uvicorn pyyaml + +# 4. 构建前端 +cd src/frontend && npm install && npm run build && cd ../.. + +# 5. 启动 PM2 +pm2 start ecosystem.config.cjs + +# 6. 验证 +curl http://127.0.0.1:8083/api/daemon/status +curl http://127.0.0.1:8083/ # 前端页面 +``` + +### 6.2 日常更新 + +```bash +# 1. 同步代码 +rsync -av --exclude='.venv' --exclude='node_modules' --exclude='.git' \ + ~/.openclaw/sanguo_projects/sanguo_moziplus_v2/ \ + ~/.sanguo_projects/sanguo_moziplus_v2/ + +# 2. 如果前端有变更 +cd ~/.sanguo_projects/sanguo_moziplus_v2/src/frontend && npm run build && cd ../.. + +# 3. 重启 +pm2 restart sanguo-moziplus-v2 + +# 4. 验证 +curl http://127.0.0.1:8083/api/daemon/status +``` + +### 6.3 创建项目 + +```bash +# 通过 CLI 创建 +python3 src/cli/admin.py project create \ + --name "量化实战" \ + --id "sanguo_quant_live" \ + --agents "pangtong-fujunshi,simayi-challenger,zhangfei-dev,guanyu-dev,zhaoyun-data,jiangwei-infra" + +# 自动创建 projects/sanguo_quant_live/ 目录和 blackboard.db +``` + +--- + +## 7. 回滚方案 + +| 场景 | 回滚方式 | +|------|---------| +| v2 启动失败 | `pm2 stop sanguo-moziplus-v2`,v1 (8082) 不受影响 | +| Daemon tick 异常 | API `POST /api/daemon/stop` 停 ticker 不停服务 | +| 单项目数据库损坏 | 删除该项目的 `blackboard.db`,重启自动重建 | +| 全局不可用 | v1 仍在 8082 运行,切换回 v1 | +| 前端构建失败 | 回退 `dist/` 目录到上一版 Git commit | + +**v1 和 v2 完全独立**。v2 出问题直接停掉,v1 继续服务。 + +--- + +## 8. 监控 + +### 8.1 健康端点 + +``` +GET /api/daemon/status +{ + "ticker_running": true, + "last_tick": "2026-05-16T23:00:00", + "tick_interval_seconds": 30, + "projects": { + "sanguo_quant_live": { + "active_agents": 2, + "tasks_summary": {"pending": 3, "working": 1, "review": 1, "done": 15}, + "db_size_bytes": 45056 + } + }, + "inbox_pending": 0, + "active_sessions": 2 +} +``` + +### 8.2 逻辑健康自检 + +Daemon 每 tick 检查:连续 N tick(默认 20,即 10 分钟)无任何任务状态变更 → 写 observation 告警 + 通知用户。 + +PM2 只能检测进程崩溃,逻辑死循环/卡死需要应用层检测。 + +### 8.3 日志 + +```bash +# Tick 日志 +pm2 logs sanguo-moziplus-v2 --lines 100 | grep "Tick" + +# Agent spawn 日志 +pm2 logs sanguo-moziplus-v2 --lines 100 | grep "Spawning" + +# 审查日志 +pm2 logs sanguo-moziplus-v2 --lines 100 | grep "review\|rebuttal" +``` + +### 8.4 SSE 推送监控 + +前端通过 `/api/events` SSE 接收实时事件。推送 4 级: + +| 级别 | 图标 | 场景 | +|------|------|------| +| 🔴 紧急 | 任务失败/系统异常 | 立即推 | +| 🟡 需关注 | 任务超时/审查不通过 | 实时推 | +| 🟢 日常 | 任务完成/日报 | 批量推 | +| 🔵 可选 | Agent 活动日志 | 用户订阅 | + +--- + +## 9. 安全 | 项目 | 措施 | |------|------| -| SQLite 文件权限 | `blackboard.db` 只有 owner 可读写(0600)| -| API 认证 | 复用 moziplus 现有认证(如有)| -| CLI 路径 | blackboard.py 只能本地 exec 调用,不暴露网络 | -| Session 清理锁 | fcntl 文件锁防止并发编辑 sessions.json | -| Agent 权限 | SOUL.md 约束 + blackboard.py claim 时的 assignee 检查 | +| SQLite 文件权限 | `blackboard.db` owner-only 读写(0600) | +| API 认证 | 内网环境,暂不认证;后续可加 API Key | +| CLI 限制 | blackboard.py 只能本地 exec,不暴露网络 | +| Agent 权限 | SOUL.md 约束 + claim assignee 检查 | +| 项目隔离 | per-project SQLite 物理隔离,一个 WHERE 漏掉也不会跨项目 | +| Session 清理 | fcntl 文件锁保护 sessions.json 编辑 | +| 归档安全 | 项目归档前必须无 working 状态任务 | --- -## 7. 性能预估 +## 10. 性能预估 | 指标 | 预估值 | 理由 | |------|--------|------| -| Tick 循环耗时 | <100ms | 6 张表、几十条记录的 SQLite 查询 | -| Agent spawn 延迟 | 2-5s | openclaw agent 冷启动时间 | -| 并发 Agent 数 | ≤6 | 6 个将军,通常不会同时活跃 | -| SQLite 并发写入 | WAL 模式支持读写并发 | 已验证 | -| blackboard.db 大小 | 初期 <1MB | 每个任务几 KB,100 个任务 < 1MB | +| Tick 耗时 | <50ms | 单项目 <10 张表几十条记录 | +| Agent spawn 延迟 | 2-5s | openclaw agent 冷启动 | +| 并发 Agent 数 | ≤5(全局) | ActiveAgentCounter 控制 | +| 项目数上限 | ~20 | SQLite 单文件无压力,PM2 不新增进程 | +| Inbox 文件大小 | <200KB | 每秒 truncate,崩溃积压 ~200KB/1000条 | +| blackboard.db 大小 | <5MB/项目 | 每任务几 KB,含 experiences | +| 前端首屏加载 | <2s | Vite 构建优化 + 本地网络 | --- -## 8. 交付检查清单 +## 11. v1 → v2 迁移计划 -Phase 1 部署前逐项验证: +``` +Phase 1: v2 后端验证(v1 不动) + ├── v2 部署到 8083 + ├── CLI 验证全流程 + └── E2E 测试通过 + +Phase 2: v2 前端验证 + ├── 前端构建部署 + ├── Dashboard 功能验证 + └── SSE 推送验证 + +Phase 3: 并行运行 + ├── v1 继续服务(8082) + ├── v2 接受新任务(8083) + └── 对比 v1/v2 行为一致性 + +Phase 4: v1 下线 + ├── pm2 stop sanguo-moziplus + ├── pm2 delete sanguo-moziplus + ├── v2 可选接管 8082 + └── v1 代码和数据库保留只读(历史归档) + +Phase 5: Mail 逐步下线 + ├── 黑板评论替代 Mail 协作 + ├── 逐个 Agent 关闭 Mail poller + └── 最终只保留 Mail 作为外部通知通道 +``` + +--- + +## 12. 交付检查清单 + +P1 部署前逐项验证: - [ ] 项目创建、git init、远程配置完成 -- [ ] `blackboard.db` 自动创建且 schema 正确 -- [ ] CLI `blackboard.py read/claim/output/comment/decide/observe/create` 全部可用 -- [ ] Daemon tick 60s 循环正常运行 -- [ ] Agent spawn 成功创建隔离 session -- [ ] Session 完成后自动存档 + sessions.json 清理 -- [ ] API `/api/blackboard/tasks` 可创建/查询任务 -- [ ] API `/api/daemon/status` 返回正确状态 -- [ ] API `/api/daemon/tick` 可手动触发 -- [ ] PM2 启动后 daemon ticker 自动恢复 -- [ ] `pm2 logs` 中能看到 tick 和 spawn 日志 +- [ ] PM2 配置正确,`pm2 start` 成功 +- [ ] 全局注册表 `registry.db` 自动创建 +- [ ] CLI `admin.py project create` 创建项目成功 +- [ ] per-project `blackboard.db` 自动创建且 schema 正确(含 reviews/experiences/comments.comment_type) +- [ ] CLI `blackboard.py read/claim/output/comment/decide/observe/create/review` 全部可用 +- [ ] Daemon tick 30s 循环正常运行 +- [ ] Inbox JSONL watcher 正常消费 + truncate +- [ ] Agent spawn 成功(Popen 非阻塞 + sessions_spawn) +- [ ] Session 完成后自动存档 +- [ ] ActiveAgentCounter 并发控制生效 +- [ ] API 端点全部可用(/api/projects/ /api/daemon/ /api/events) +- [ ] SSE 推送正常工作 +- [ ] 前端构建产物可访问(8083 端口) +- [ ] 健康端点返回正确状态 +- [ ] 逻辑健康自检(连续 20 tick 无变更→告警) - [ ] v1 (8082) 不受 v2 (8083) 影响 - ---- - -## 9. 后续 Phase 规划 - -| Phase | 内容 | 依赖 | -|-------|------|------| -| **Phase 1** | 黑板 + Daemon + CLI + API(本方案) | 无 | -| Phase 2 | 前端黑板视图 + Agent 黑板 Skill | Phase 1 | -| Phase 3 | 依赖自动推进 + 产出验证门禁 | Phase 2 | -| Phase 4 | 庞统 AI 规划 + Agent 自主领活 | Phase 3 | -| Phase 5 | 经验沉淀 + Mail 完全移除 | Phase 4 |