# v2.7 三级层次结构完整设计文档 > 日期:2026-05-17 > 版本:v1.0 > 作者:庞统 > 状态:待评审 > 变更记录:与用户 6 轮讨论后定稿 --- ## 一、核心架构 ### 1.1 三层结构 ``` Project(项目) └── Card(卡片/策略/工作流) └── Task(原子任务) ``` | 层级 | 语义 | 例子 | 生命周期 | |------|------|------|---------| | **Project** | 业务领域/产品线 | sanguo_quant_live、General、Mail | 长期 | | **Card** | 独立的工作流/策略 | 动量策略v1、v2.7开发 | 中期(天/周) | | **Task** | 原子执行单元 | 编写回测脚本、清洗分钟线 | 短期(小时/天) | ### 1.2 隔离策略 **一个 Project 一个 DB + card_id 逻辑隔离。** 理由: - Jira/Linear/Asana 均采用逻辑隔离,是成熟模式 - 跨 Card 查询天然支持(同一 DB) - 备份/迁移按 Project 独立 - 单 DB <5000 Task,SQLite 性能无忧 **跨 Card 依赖不支持**——策略间应独立,数据引用用 artifacts 路径。 ### 1.3 Card 状态 = Task 状态聚合 Card 不独立维护状态机,状态从内部 Task 推导(取最高水位): | Card 状态 | 推导规则 | 可创建 Task | Ticker 扫描 | |-----------|---------|------------|------------| | pending | 所有 Task 都是 pending | ✅ | ✅ | | working | 有 Task 在 working | ✅ | ✅ | | review | 有 Task 在 review | ✅ | ✅ | | done | 所有 Task 都是 done | ❌ | ❌ | | failed | 有 Task failed 且无 active Task | ❌ | ❌ | | blocked | 有 Task blocked 且无 active Task | ❌ | ✅(检查是否解除) | | cancelled | 用户/AI 取消 | ❌ | ❌ | | **archived** | 用户/AI 归档 | ❌ | ❌ | | **deleted** | 系统清理 | ❌ | ❌ | 额外两个状态(超出 Task 语义): - **archived**:人工/AI 归档决策,默认视图不显示,可切换查看 - **deleted**:archived 后 7-30 天物理清理 ### 1.4 Stage 进度(AI 动态生成) Card 创建时 AI 根据目标描述生成初始 Stages,执行中可动态调整: ``` Card: 动量策略v1 Stages(AI 生成,可演进): [因子研究 ✅] → [策略编码 ✅] → [历史回测 🔄] → [参数优化 ⬜] ↑ AI 发现需要先做数据质量检查,动态插入新 Stage ``` 数据模型: - `cards.stages_json`:存当前 stages 定义 - `tasks.stage`:Task 绑定到某个 stage id Stage 不是状态机——Task 可以在任意 stage 创建,stage 只用于分组显示进度。 --- ## 二、特殊 Project ### 2.1 General(一般性任务) - Project ID:`_general` - 用途:无项目归属的 ad-hoc 任务 - 用户随口说的"帮我下载分钟线"→ 自动创建到 General - 在 Dashboard 中作为一个普通 Project 显示 ### 2.2 Mail(邮件系统) - Project ID:`_mail` - 用途:Agent 间 Mail 通信 - **独立 Tab 页面**,list 形式展示 - 显示字段:时间 | From | To | Title | 状态(已读/未读/已执行) - 未来用户说"给司马懿发 mail"→ 在此 Project 创建 Task - 不在主 Dashboard 的 Card 看板中显示 ### 2.3 特殊 Project 列表 | Project ID | 显示位置 | 展示形式 | |-----------|---------|---------| | `_general` | Dashboard(普通 Project) | Card 看板 | | `_mail` | 独立 Tab 页 | 列表 | | 其他用户 Project | Dashboard | Card 看板 | --- ## 三、项目管理 ### 3.1 项目发现 **自动发现 + 注册表补充元数据,不强制。** - 系统启动时扫描 `~/.sanguo_projects/` 目录 - 新发现的目录自动添加到 registry(标记 `source=auto_discovered`) - 用户可手动补充名称、描述、配置 - 已注册的项目以注册表为准 ### 3.2 项目 CRUD | 操作 | 实现 | |------|------| | 自动发现 | 扫描 sanguo_projects 目录 | | 手动创建 | `POST /api/projects` | | 修改元数据 | `PATCH /api/projects/{pid}` | | 归档 | `PATCH /api/projects/{pid}` status→archived(级联归档所有 Card) | | 删除 | archived 后 7-30 天物理清理 | --- ## 四、数据模型 ### 4.1 Registry DB(全局) 路径:`data/registry.db` ```sql CREATE TABLE IF NOT EXISTS projects ( id TEXT PRIMARY KEY, name TEXT NOT NULL, description TEXT DEFAULT '', status TEXT DEFAULT 'active', source TEXT DEFAULT 'manual', -- manual / auto_discovered config_json TEXT DEFAULT '{}', created_at TEXT NOT NULL, updated_at TEXT ); ``` ### 4.2 Project DB(per-project) 路径:`data/{pid}/blackboard.db` **新增 cards 表:** ```sql CREATE TABLE IF NOT EXISTS cards ( id TEXT PRIMARY KEY, name TEXT NOT NULL, description TEXT DEFAULT '', card_type TEXT DEFAULT 'default', -- default/strategy/data_pipeline/research stages_json TEXT DEFAULT '[]', -- AI 生成的阶段定义 labels_json TEXT DEFAULT '[]', created_at TEXT NOT NULL, updated_at TEXT, archived_at TEXT ); CREATE INDEX IF NOT EXISTS idx_cards_id ON cards(id); ``` **所有现有表加 card_id:** ```sql ALTER TABLE tasks ADD COLUMN card_id TEXT; ALTER TABLE tasks ADD COLUMN stage TEXT DEFAULT NULL; CREATE INDEX IF NOT EXISTS idx_tasks_card ON tasks(card_id); ALTER TABLE outputs ADD COLUMN card_id TEXT; ALTER TABLE reviews ADD COLUMN card_id TEXT; ALTER TABLE comments ADD COLUMN card_id TEXT; ALTER TABLE events ADD COLUMN card_id TEXT; CREATE INDEX IF NOT EXISTS idx_events_card ON events(card_id); ALTER TABLE task_attempts ADD COLUMN card_id TEXT; ALTER TABLE routing_decisions ADD COLUMN card_id TEXT; ``` **DDL 变更策略:** - 新 DB:CREATE TABLE 直接包含 card_id 和 stage - 旧 DB:`_migrate_v27()` ALTER TABLE + 创建默认 Card + 回填 ### 4.3 默认 Card - 每个 Project 自动创建一个 `default` Card - 迁移时所有现有数据的 card_id 设为 `default` - 用户可以直接在 default Card 上工作(不感知 Card 层) ### 4.4 目录结构 ``` data/ ├── registry.db ├── _general/ │ ├── blackboard.db │ └── artifacts/ ├── _mail/ │ ├── blackboard.db │ └── artifacts/ ├── sanguo_quant_live/ │ ├── blackboard.db │ └── artifacts/ ├── sanguo_vnpy/ │ ├── blackboard.db │ └── artifacts/ └── sanguo_moziplus_v2/ ├── blackboard.db └── artifacts/ ``` --- ## 五、API 路由 ### 5.1 Project 级 ``` GET /api/projects → 列出所有项目(含自动发现的) POST /api/projects → 手动创建项目 GET /api/projects/{pid} → 项目详情 + 聚合统计 PATCH /api/projects/{pid} → 更新项目元数据 DELETE /api/projects/{pid} → 删除项目(archived 后) ``` ### 5.2 Card 级 ``` GET /api/projects/{pid}/cards → 列出所有 Card POST /api/projects/{pid}/cards → 创建 Card GET /api/projects/{pid}/cards/{cid} → Card 详情 + Stage 进度 PATCH /api/projects/{pid}/cards/{cid} → 更新 Card(改名/归档/调整 stages) DELETE /api/projects/{pid}/cards/{cid} → 删除 Card POST /api/projects/{pid}/cards/{cid}/fork → Fork Card(策略迭代) ``` ### 5.3 Task 级 ``` GET /api/projects/{pid}/cards/{cid}/tasks → Card 下所有 Task POST /api/projects/{pid}/cards/{cid}/tasks → 创建 Task GET /api/projects/{pid}/cards/{cid}/tasks/{tid} → Task 详情 POST /api/projects/{pid}/cards/{cid}/tasks/{tid}/status → 更新状态 POST /api/projects/{pid}/cards/{cid}/tasks/{tid}/outputs → 添加产出 POST /api/projects/{pid}/cards/{cid}/tasks/{tid}/reviews → 添加审查 POST /api/projects/{pid}/cards/{cid}/tasks/{tid}/comments → 添加评论 ``` ### 5.4 便利路由 ``` GET /api/projects/{pid}/tasks → Project 下所有 active cards 的 tasks(合并) GET /api/projects/{pid}/events → Project 下所有事件 ``` ### 5.5 Mail Tab ``` GET /api/mail → Mail 列表(from/to/title/status/time) GET /api/mail/{id} → Mail 详情 PATCH /api/mail/{id} → 标记已读/已执行 ``` ### 5.6 向后兼容 - 旧路由 `/api/projects/{pid}/tasks` 保留,内部查所有 active cards - 不传 card_id 时自动使用 `default` Card - 前端渐进迁移 --- ## 六、Ticker 变更 ### 6.1 扫描逻辑 ```python for project in registry.list_projects(status='active'): db_path = data_root / project.id / "blackboard.db" active_cards = card_ops.list_cards(db_path, status='active') for card in active_cards: tick_card(db_path, card.id) ``` ### 6.2 性能 - 单 DB 内按 card_id 查询,索引命中,微秒级 - active cards 过多时加 LIMIT 分批 --- ## 七、上下文隔离 ### 7.1 Agent 视角 Agent 执行 Task 时,prompt 只注入当前 Card 的数据: ```python context = queries.build_agent_context(db_path, task_id, card_id=task.card_id) ``` ### 7.2 写入自动带 card_id Agent 写 output、改 status 时,API 自动从 Task 关联获取 card_id,Agent 不感知。 ### 7.3 跨 Card 引用 Fork Card 时可注入源 Card 的摘要。写入仍在当前 Card。 --- ## 八、Stage 进度 ### 8.1 AI 动态生成 1. Card 创建时,AI 根据目标描述生成初始 stages → 写入 `stages_json` 2. 执行中 Agent 可提议修改 stages(新增/删除/重排)→ 更新 `stages_json` 3. 用户可手动调整 4. Task 绑定 stage,前端按 stage 分组显示 ### 8.2 进度计算 ```python def card_progress(db_path, card_id, stages): for stage in stages: total = count(tasks WHERE card_id=? AND stage=?) done = count(tasks WHERE card_id=? AND stage=? AND status='done') active = count(tasks WHERE card_id=? AND stage=? AND status IN ('working','review')) ``` ### 8.3 默认 Stage 不指定 stage 的 Task 归入"未分类"组。 --- ## 九、联动功能 | 阶段 | 操作 | 粒度 | 谁触发 | |------|------|------|--------| | **创建** | 创建 Project | Project | 用户/AI | | | 创建 Card | Card | 用户/AI | | | 创建 Task | Task | 用户/AI/Ticker | | **发现** | 扫描 sanguo_projects 目录 | Project | 系统 | | | 手动补充元数据 | Project | 用户 | | **规划** | AI 生成 Stages | Card | AI | | | AI 动态调整 Stages | Card | AI 提议 | | | 用户调整 Stages | Card | 用户 | | **执行** | Agent 执行 Task | Task | Ticker | | | Review 流转 | Task | Ticker/Agent | | | 重试/暂停/取消 Task | Task | Ticker/用户/AI | | **进度** | Stage 进度条 | Card | 自动推导 | | | Card 状态聚合 | Card | 自动推导 | | | Project 整体进度 | Project | 自动推导 | | **查询** | 单 Card 查询 | Card | 用户/AI | | | 单 Project 查询 | Project | 用户/AI | | | 全局任务列表 | 跨 Project | 用户/AI | | **暂停** | 暂停 Card | Card | 用户/AI | | | 暂停 Project | Project | 用户 | | **取消** | 取消 Card | Card | 用户/AI | | | 取消 Project | Project | 用户 | | **归档** | 归档 Card | Card | 用户/AI | | | 归档 Project(级联 Card) | Project | 用户 | | | 查看归档数据 | Card/Project | 用户 | | **删除** | 物理清理(归档 7-30 天后) | Card/Project | 系统 | | | 立即删除 | Card/Project | 用户 | | **恢复** | 归档 → active | Card/Project | 用户 | | | 已删除 → 恢复(7天内) | Card/Project | 用户 | | **Fork** | 从已有 Card 创建新 Card | Card | 用户/AI | | **移动** | Task 跨 Card 移动 | Task | 用户 | | | Card 跨 Project 移动 | Card | 用户 | --- ## 十、前端设计 ### 10.1 页面结构 ``` ┌─────────────────────────────────────────────────┐ │ [Dashboard] [Mail] [Settings] │ ← 顶部 Tab ├─────────────────────────────────────────────────┤ │ 左侧:Project 导航 │ │ ├── General │ │ ├── sanguo_quant_live │ │ ├── sanguo_vnpy │ │ └── sanguo_moziplus_v2 │ ├─────────────────────────────────────────────────┤ │ 右侧:Card 看板 / Mail 列表 │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ Card 1 │ │ Card 2 │ │ Card 3 │ │ │ │ ■■■□ 75% │ │ ■□□□ 20% │ │ □□□□ 0% │ │ │ └──────────┘ └──────────┘ └──────────┘ │ │ │ │ [Stage 进度条] [Task 列表] [事件流] │ └─────────────────────────────────────────────────┘ ``` ### 10.2 Mail Tab | 时间 | From | To | Title | 状态 | |------|------|----|-------|------| | 22:30 | simayi | pangtong | 路由方案评审通过 | ✅ 已读 | | 22:15 | pangtong | simayi | 代码评审请求 | 📬 未读 | | 21:40 | zhangfei | pangtong | e2e-rt-002 完成 | ✅ 已执行 | ### 10.3 Card 详情 - 顶部:Stage 进度条 - 中部:Task 列表(按 stage 分组) - 底部:事件流 / 评论 --- ## 十一、路由方案兼容性 完全兼容: - routing_decisions 表加 card_id - agent_profiles 和 routing 配置在 Project 级 - AgentRouter per-Project,Card 只是查询过滤条件 --- ## 十二、数据迁移 ```python def migrate_v27(db_path): # 1. 创建 cards 表 # 2. 所有表加 card_id + stage # 3. 创建 default Card # 4. 回填 card_id = 'default' # 5. 创建索引 def migrate_registry(data_root): # 读 _registry.yaml → 写 registry.db # 扫描 sanguo_projects 目录 → 补充 auto_discovered ``` --- ## 十三、实施计划 ### v2.7.0 范围 | 序号 | 任务 | 预计 | |------|------|------| | 1 | registry.db + ProjectRegistry + 自动发现 | 0.5 天 | | 2 | cards 表 + 所有表加 card_id + stage + 迁移 | 0.5 天 | | 3 | CardOps + Blackboard/Queries 加 card_id | 1 天 | | 4 | API 路由(Card CRUD + Task 嵌套 + Mail) | 1 天 | | 5 | Ticker 适配(per-card 扫描) | 0.5 天 | | 6 | 前端 Dashboard 重构(Card 看板 + Stage 进度) | 1.5 天 | | 7 | 前端 Mail Tab | 0.5 天 | | 8 | 端到端测试 + 迁移验证 | 0.5 天 | | **合计** | | **6 天** | ### 不在 v2.7.0 范围 - Card 模板系统(Phase 2) - 全局搜索/FTS(Phase 2) - 跨 Project 统计报表(Phase 2) - 冷存储迁移脚本(按需) ### 前置条件 - ✅ v2.6.1 路由方案已落地并 E2E 验证