Files
sanguo_moziplus_v2/docs/design/v2.7-subtask-model.md
T
2026-05-18 08:24:10 +08:00

327 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# v2.7 数据模型重新设计:Project → Task → SubTask
> 日期:2026-05-18
> 版本:v1.0(基于 2026-05-18 08:13 ~ 08:21 讨论定稿)
> 作者:庞统
> 状态:待确认
> 前置:回滚 v2.7 Card 层(设计文档 + 代码)
---
## 一、概念对齐
| 层级 | 语义 | 例子 | 谁创建 | 生命周期 |
|------|------|------|--------|---------|
| **Project** | 仓库/组织 | sanguo_quant_live、sanguo_vnpy | 系统(自动发现)+ 用户 | 长期 |
| **Task** | 用户的一条需求/意图/目标 | "动量策略v1"、"下载分钟线"、"v2.7开发" | 用户 / AI | 天~周 |
| **SubTask** | Agent 领走执行的原子动作 | 张飞编码、赵云备数据、司马懿评审 | AI(庞统分解)| 小时~天 |
### 关键认知
1. **Task 是用户视角的最小单位**:用户说"帮我做动量策略v1",这就是一个 Task
2. **SubTask 是 Agent 视角的最小单位**:庞统把 Task 拆解后分发给各将军
3. **SubTask 可以跨 Project**:姜维在 sanguo_vnpy 搭回测引擎,服务的是 sanguo_quant_live 的 Task
4. **SubTask ≈ Stage**:同一个 Task 的 SubTask 按执行顺序形成 Stage 链
5. **Task 间有依赖**:策略编码依赖数据准备,实盘依赖模拟验证
---
## 二、回滚范围
### 回滚 Card 相关代码(开发目录)
| 文件 | 操作 |
|------|------|
| `src/blackboard/models.py` | 删除 Card 相关代码(CARD_VALID_STATUSES 等 + Card dataclass |
| `src/blackboard/db.py` | 删除 `_CARDS_SCHEMA``_migrate_v27()`、cards 表 DDLtasks 表移除 `card_id``stage` 列 |
| `src/blackboard/operations.py` | 删除 CardOps 类(create_card / list_cards / fork_card 等) |
| `src/blackboard/queries.py` | 移除 card_id 过滤参数 |
| `src/api/card_routes.py` | **删除整个文件** |
| `src/api/mail_routes.py` | **删除整个文件**Mail 后续重新设计) |
| `src/blackboard/registry.py` | 保留 ProjectRegistry(不涉及 Card |
| `src/daemon/ticker.py` | 移除 per-card 扫描逻辑,恢复 v2.6 per-project 扫描 |
| `src/main.py` | 移除 card_routes、mail_routes 注册;移除 v2.7 迁移调用 |
| `tests/test_v27_cards.py` | **删除整个文件** |
### 回滚设计文档
| 文件 | 操作 |
|------|------|
| `docs/design/v2.7-three-tier-hierarchy.md` | 归档到 `docs/design/archive/` |
### 保留
| 文件/功能 | 原因 |
|-----------|------|
| `registry.db` + ProjectRegistry + 自动发现 | Project 管理需要 |
| per-project `blackboard.db` | 多项目隔离需要 |
| Project API 路由 | 前端项目选择器需要 |
| Product 方向备忘录 | 新增,记录未来方向 |
---
## 三、新增:SubTask 层
### 3.1 数据模型
**SubTask 表**(加到 per-project blackboard.db):
```sql
CREATE TABLE IF NOT EXISTS subtasks (
id TEXT PRIMARY KEY, -- 自动生成(如 st-a1b2c3
task_id TEXT NOT NULL REFERENCES tasks(id), -- 所属 Task
title TEXT NOT NULL, -- 如 "策略编码"、"数据清洗"
description TEXT DEFAULT '',
status TEXT NOT NULL DEFAULT 'pending'
CHECK (status IN ('pending','claimed','working','review','done','failed','blocked','cancelled')),
assignee TEXT, -- 执行 Agent(如 zhangfei-dev
assigned_by TEXT, -- 分配者(通常是 pangtong-fujunshi
stage TEXT DEFAULT NULL, -- 所属 Stage 标签(如 "research"、"coding"
stage_order INTEGER DEFAULT 0, -- Stage 内排序
depends_on TEXT, -- JSON array of subtask idsSubTask 间依赖)
output_summary TEXT DEFAULT NULL, -- 产出物摘要
output_path TEXT DEFAULT NULL, -- 产出物路径
parent_project TEXT DEFAULT NULL, -- 实际工作所在 Project(跨项目时用)
retry_count INTEGER NOT NULL DEFAULT 0,
max_retries INTEGER NOT NULL DEFAULT 2,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
started_at TEXT,
completed_at TEXT
);
CREATE INDEX IF NOT EXISTS idx_subtasks_task ON subtasks(task_id);
CREATE INDEX IF NOT EXISTS idx_subtasks_status ON subtasks(status);
CREATE INDEX IF NOT EXISTS idx_subtasks_assignee ON subtasks(assignee);
CREATE INDEX IF NOT EXISTS idx_subtasks_stage ON subtasks(task_id, stage);
```
### 3.2 Task 表变更
在现有 tasks 表基础上,新增字段:
```sql
ALTER TABLE tasks ADD COLUMN stages_json TEXT DEFAULT '[]'; -- Stage 定义(AI 生成)
ALTER TABLE tasks ADD COLUMN plan_json TEXT DEFAULT NULL; -- 完整分解计划(庞统生成)
```
**`stages_json` 格式**
```json
[
{"id": "research", "label": "因子研究", "order": 1},
{"id": "data_prep", "label": "数据准备", "order": 2},
{"id": "coding", "label": "策略编码", "order": 3},
{"id": "backtest", "label": "历史回测", "order": 4},
{"id": "optimize", "label": "参数优化", "order": 5}
]
```
**`plan_json` 格式**
```json
{
"version": 1,
"created_by": "pangtong-fujunshi",
"created_at": "2026-05-18T08:00:00Z",
"stages": [...],
"subtasks": [
{
"id": "st-001",
"title": "因子研究",
"assignee": "zhangfei-dev",
"stage": "research",
"depends_on": [],
"parent_project": null
},
{
"id": "st-002",
"title": "分钟线数据下载",
"assignee": "zhaoyun-data",
"stage": "data_prep",
"depends_on": [],
"parent_project": null
},
{
"id": "st-003",
"title": "策略编码",
"assignee": "zhangfei-dev",
"stage": "coding",
"depends_on": ["st-001", "st-002"],
"parent_project": null
},
{
"id": "st-004",
"title": "回测引擎搭建",
"assignee": "jiangwei-infra",
"stage": "backtest",
"depends_on": [],
"parent_project": "sanguo_vnpy"
}
]
}
```
### 3.3 跨项目 SubTask
**`parent_project` 字段**
- `NULL`SubTask 在当前 Project 内执行
- `"sanguo_vnpy"`:SubTask 实际工作在另一个 Project 目录
跨项目 SubTask 的执行流程:
1. 庞统在 Task Asanguo_quant_live)分解时,识别到需要回测引擎
2. 创建 SubTask st-004`parent_project=sanguo_vnpy`
3. Ticker 在 sanguo_vnpy 项目也扫描到这个 SubTask(通过 cross-project 查询)
4. 姜维在 sanguo_vnpy 执行完成后,结果写回 Task A 的 SubTask
**注意**:跨项目执行是复杂场景,v2.7 先做数据模型支持(字段存在),执行逻辑后续迭代。
### 3.4 现有表关联 SubTask
以下表新增 `subtask_id` 字段(可选,向后兼容):
```sql
ALTER TABLE events ADD COLUMN subtask_id TEXT;
ALTER TABLE comments ADD COLUMN subtask_id TEXT;
ALTER TABLE outputs ADD COLUMN subtask_id TEXT;
ALTER TABLE task_attempts ADD COLUMN subtask_id TEXT;
```
这样 Events、Comments、Outputs 既可以关联到 Task 级别,也可以精确到 SubTask 级别。
---
## 四、Task 状态 = SubTask 状态聚合
Task 不独立维护复杂状态机,核心状态从 SubTask 推导(类似之前 Card 的聚合逻辑,但语义更自然):
| Task 状态 | 推导规则 |
|-----------|---------|
| `pending` | 所有 SubTask 都是 pending,或无 SubTask |
| `working` | 有 SubTask 在 working |
| `review` | 有 SubTask 在 review |
| `done` | 所有 SubTask 都是 done |
| `failed` | 有 SubTask failed 且无 active SubTask |
| `blocked` | 有 SubTask blocked 且无 active SubTask |
| `cancelled` | 用户/AI 取消(手动设置) |
**额外状态**(不属于聚合,手动设置):
- `planning`:庞统正在分解 Task(生成 plan_json
- `challenging`:司马懿正在审核分解方案
---
## 五、API 路由
### 5.1 Task 级(已有,微调)
```
GET /api/projects/{pid}/tasks → Task 列表(含 SubTask 聚合状态)
POST /api/projects/{pid}/tasks → 创建 Task(用户需求)
GET /api/projects/{pid}/tasks/{tid} → Task 详情 + Stage 进度
PATCH /api/projects/{pid}/tasks/{tid} → 更新 Task(如取消、改优先级)
DELETE /api/projects/{pid}/tasks/{tid} → 删除 Task
```
### 5.2 SubTask 级(新增)
```
GET /api/projects/{pid}/tasks/{tid}/subtasks → Task 下所有 SubTask(按 Stage 分组)
POST /api/projects/{pid}/tasks/{tid}/subtasks → 创建 SubTaskAI/手动)
GET /api/projects/{pid}/tasks/{tid}/subtasks/{stid} → SubTask 详情
PATCH /api/projects/{pid}/tasks/{tid}/subtasks/{stid} → 更新 SubTask(状态、指派)
POST /api/projects/{pid}/tasks/{tid}/subtasks/{stid}/status → 更新状态(Agent 回调)
POST /api/projects/{pid}/tasks/{tid}/subtasks/{stid}/outputs → 提交产出
```
### 5.3 便利路由
```
GET /api/projects/{pid}/tasks/{tid}/progress → Stage 进度条数据
GET /api/projects/{pid}/subtasks → 项目级所有 SubTask(跨 Task 查询)
```
### 5.4 向后兼容
- 旧路由 `/api/projects/{pid}/tasks` 保留
- 不传 SubTask 相关参数时行为不变
- Task 的 status 仍然可用(聚合推导)
---
## 六、Ticker 变更
### 6.1 扫描逻辑
```python
for project in registry.list_projects(status='active'):
db_path = data_root / project.id / "blackboard.db"
tasks = queries.tasks_by_status(db_path, ['pending', 'working', 'planning'])
for task in tasks:
# 1. 如果 Task 在 planning → 触发庞统分解
if task.status == 'planning':
dispatch_planning(task)
continue
# 2. 扫描 Task 下 pending 的 SubTask
pending = queries.pending_subtasks(db_path, task.id)
for subtask in pending:
if deps_satisfied(subtask):
dispatch_subtask(subtask)
# 3. 聚合刷新 Task 状态
refresh_task_status(db_path, task.id)
```
### 6.2 调度粒度
- **调度单位**SubTask(不是 Task
- **状态聚合**:每次 tick 刷新 Task 的聚合状态
- **max_dispatch_per_tick**:全局限制(恢复 v2.6 语义)
---
## 七、前端改动(最小)
### 7.1 不改的
- 整体布局不变(Tab 栏 + 内容区)
- 项目选择器保持下拉菜单
- EdictBoardTask 看板)基本不变
### 7.2 改的
1. **Task 详情弹窗(TaskModal.tsx**
- 新增 Stage 进度条(从 stages_json 读取)
- SubTask 列表(按 Stage 分组)
- 每个 SubTask 显示:标题、Agent、状态、产出
2. **Task 看板卡片**
- 加 Stage 进度指示器(小进度条)
3. **Mail Tab**(后续独立实现):
- 新增 Tab,列表展示 Sanguo Mail
### 7.3 暂不做的
- 独立的 SubTask 看板/管理页面
- 跨 Project 的 Product 视图
- Card 看板
---
## 八、实施计划
| 序号 | 任务 | 预计 |
|------|------|------|
| 1 | 回滚 Card 层(代码 + 设计文档归档) | 2h |
| 2 | 新增 SubTask 表 + models + operations | 3h |
| 3 | Task 表加 stages_json/plan_json + 聚合状态 | 2h |
| 4 | SubTask API 路由 | 2h |
| 5 | Ticker 适配(per-SubTask 调度 + 状态聚合) | 2h |
| 6 | 前端 Task 详情弹窗改造(Stage 进度 + SubTask 列表) | 3h |
| 7 | 测试 + 司马懿评审 | 2h |
| **合计** | | **~16h** |
### 优先级
先回滚(1)→ 再建 SubTask(2-5)→ 前端(6)→ 评审测试(7)