[moz] docs(§22): v1.3 §22.6 TC Discuss 重构 + §22.8 TC Round Review Gitea 适配设计
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
---
|
||||
title: "End-to-End Flow — 端到端任务流程设计"
|
||||
created: 2026-06-22
|
||||
version: v1.2
|
||||
version: v1.3
|
||||
status: draft
|
||||
changelog: v1.2 §22.3/§22.4 更新 Phase 1 为 ✅ 已实现(PR #124)
|
||||
changelog: v1.3 §22.6 重构为「所有 TC 流程第一步走 Discuss」+ §22.8 TC Round Review Gitea 适配设计
|
||||
v1.2 §22.3/§22.4 更新 Phase 1 为 ✅ 已实现(PR #124)
|
||||
v1.1 补充轻量路径设计(§22.6)、数据流澄清(§22.7)、修正设计原则3、统一Phase编号、Phase 1标注
|
||||
v1.0 初版
|
||||
---
|
||||
@@ -264,35 +265,65 @@ issue_assigned:
|
||||
|
||||
## §22.6 轻量路径设计(Direct Assignment)
|
||||
|
||||
> 不是所有任务都需要 Discussion 广播。需求明确、单一执行者的任务应跳过 Phase 0/1 直接进入 Phase 2。
|
||||
> **核心原则:所有 TC 流程第一步都走 Discuss。**
|
||||
> Discussion 不是可选项,而是 TC 流程的必经阶段——确保方案对齐、风险暴露后再进入 exec。
|
||||
> 区别只在于「谁参与讨论」。
|
||||
|
||||
### 路径决策矩阵
|
||||
|
||||
| 条件 | 路径 | 流程 |
|
||||
|------|------|------|
|
||||
| Issue 无 assignee + type/* label | **Discussion 路径**(默认) | Phase 0 → 1 → 2 → … |
|
||||
| Issue 有 assignee | **Direct 路径** | → Phase 2(跳过 Phase 0/1) |
|
||||
| Issue 有 `flow/direct` label | **强制 Direct** | → Phase 2(即使无 assignee,daemon 自动 assign) |
|
||||
| Issue 有 `flow/discuss` label | **强制 Discussion** | Phase 0 → 1 → 2 → …(即使有 assignee) |
|
||||
| 条件 | 讨论范围 | 流程 |
|
||||
|------|---------|------|
|
||||
| Issue 无 assignee + type/* label | **广播所有空闲 agent** | Phase 0 → 1(广播讨论)→ 2 → … |
|
||||
| Issue 有 assignee | **assignee + reviewer(司马懿)定向讨论** | Phase 0 → 1(定向讨论)→ 2 → … |
|
||||
| Issue 有 `flow/direct` label | **跳过讨论** | → Phase 2(唯一跳过 Discuss 的路径) |
|
||||
|
||||
**设计原则**:
|
||||
1. 没有 `flow/direct` label → 必须走 Discuss,没有例外
|
||||
2. 有 assignee → assignee 自己写方案 + 司马懿 review 通过后才能进 exec
|
||||
3. 没有 assignee → 广播所有 agent 讨论,有 agent 认领后创建 sub Issue
|
||||
4. `flow/direct` 是唯一的逃生舱(明确不需要讨论的小改动)
|
||||
|
||||
### 判断逻辑
|
||||
|
||||
```
|
||||
parent Issue 创建
|
||||
├─ 有 flow/discuss label?→ Discussion 路径(Phase 0 → 1)
|
||||
├─ 有 flow/direct label?→ Direct 路径(daemon 自动 assign → Phase 2)
|
||||
├─ 有 assignee?→ Direct 路径(→ Phase 2)
|
||||
└─ 无 assignee(默认)→ Discussion 路径(Phase 0 → 1)
|
||||
├─ 有 flow/direct label?→ Direct 路径(→ Phase 2,跳过讨论)
|
||||
├─ 有 assignee?→ 定向 Discussion(assignee + reviewer 讨论)
|
||||
└─ 无 assignee(默认)→ 广播 Discussion(所有空闲 agent)
|
||||
```
|
||||
|
||||
优先级:`flow/*` label > assignee > 默认行为。
|
||||
### 定向讨论流程(有 assignee)
|
||||
|
||||
```
|
||||
Issue assigned webhook
|
||||
→ daemon 创建 issue_discussion task(context_data 带 assignee)
|
||||
→ ticker dispatch:检测到 assignee 不为空
|
||||
→ 只 spawn assignee + simayi-challenger(不广播其他人)
|
||||
→ discussion prompt 引导 assignee:
|
||||
1. 在 Gitea Issue comment 写实现方案(技术选型、实现路径、影响范围)
|
||||
2. 等待司马懿 review 方案
|
||||
3. review 通过 → 创建 sub Issue assign 自己 → 进入 exec
|
||||
4. review 驳回 → 修改方案重新提交
|
||||
```
|
||||
|
||||
### 广播讨论流程(无 assignee)
|
||||
|
||||
```
|
||||
Issue opened webhook
|
||||
→ daemon 创建 issue_discussion task(assignee=None)
|
||||
→ ticker broadcast:广播所有空闲 agent
|
||||
→ discussion prompt 引导每个 agent:
|
||||
1. 在 Gitea Issue comment 回应(定位/建议/认领/风险)
|
||||
2. 需要参与的 agent 创建 sub Issue assign 自己
|
||||
```
|
||||
|
||||
### 适用场景
|
||||
|
||||
| 路径 | 适用场景 | 示例 |
|
||||
|------|---------|------|
|
||||
| Discussion | 需求不明确、需要多角色讨论、跨模块协作 | 新功能设计、架构变更、涉及 3+ agent 的任务 |
|
||||
| Direct | 需求明确、单一执行者、小范围改动 | Bug 修复、文档更新、配置调整、单人任务 |
|
||||
| 广播讨论 | 需求不明确、跨模块协作、无人认领 | 新功能设计、架构变更 |
|
||||
| 定向讨论 | 需求明确但需要方案确认 | 有明确 assignee 的 Issue |
|
||||
| Direct | 改 typo、改配置值等极小改动 | `flow/direct` label |
|
||||
|
||||
### Discussion 路径中的降级
|
||||
|
||||
@@ -304,26 +335,18 @@ Discussion 进行中,如果所有 agent 都认为任务足够简单只涉及
|
||||
|
||||
庞统判断后创建 sub Issue 直接 assign → 该 agent 跳过讨论直接进入 Phase 2。
|
||||
|
||||
### Direct 路径跳过的 Phase
|
||||
### 实现方案
|
||||
|
||||
| Phase | 是否跳过 | 原因 |
|
||||
|-------|---------|------|
|
||||
| Phase 0(parent Issue 讨论 task) | ✅ 跳过 | 不创建 discussion task |
|
||||
| Phase 1(Discussion 广播) | ✅ 跳过 | 不广播,不打扰其他 agent |
|
||||
| Phase 2(assigned → executor) | ❌ 直接进入 | 起点 |
|
||||
**toolchain_routes.py**:
|
||||
- `opened` 分支(无 assignee)→ discussion task(assignee=None)— 现有逻辑 ✅
|
||||
- `assigned` 分支改为:创建 discussion task(context_data 带 assignee)— **需要改动**
|
||||
- `flow/direct` 分支 → executor task — 现有逻辑 ✅
|
||||
|
||||
### 对现有代码的影响
|
||||
**ticker.py `_broadcast_claim`**:
|
||||
- discussion task + `context.assignee` 有值 → 只 spawn assignee + simayi-challenger
|
||||
- discussion task + `context.assignee` 为空 → 广播所有空闲 agent(现有逻辑 ✅)
|
||||
|
||||
当前 `_handle_issues` 已有两个分支:
|
||||
|
||||
- `opened`(无 assignee + type/* label)→ discussion task ← Discussion 路径 ✅
|
||||
- `assigned`(有 assignee)→ executor task ← Direct 路径 ✅
|
||||
|
||||
**轻量路径已全部实现**。包括:
|
||||
|
||||
1. ✅ `flow/direct` 和 `flow/discuss` label 已创建(Gitea label id=100, 101)
|
||||
2. ✅ `toolchain_routes.py` `_handle_issues` opened 分支识别 `flow/direct` → executor task
|
||||
3. ✅ Discussion prompt 中包含降级机制引导(§22.6)
|
||||
**不影响**:mail / task 流程(它们不走 toolchain_routes.py)
|
||||
|
||||
---
|
||||
|
||||
@@ -360,29 +383,11 @@ ticker: _check_round_complete
|
||||
→ 全部终态 → spawn 庞统 review
|
||||
```
|
||||
|
||||
### 前置条件
|
||||
### 前置条件(已全部实现 ✅)
|
||||
|
||||
1. **task_state 表创建**:§20 设计了 DDL 但未实现。需要先建表:
|
||||
|
||||
```sql
|
||||
CREATE TABLE task_state (
|
||||
issue_number INTEGER PRIMARY KEY,
|
||||
repo TEXT,
|
||||
parent_issue INTEGER,
|
||||
status TEXT DEFAULT 'pending',
|
||||
action_type TEXT,
|
||||
retry_count INTEGER DEFAULT 0,
|
||||
dispatch_count INTEGER DEFAULT 0,
|
||||
round_count INTEGER DEFAULT 0,
|
||||
created_at TEXT,
|
||||
updated_at TEXT
|
||||
);
|
||||
CREATE INDEX idx_task_state_parent ON task_state(parent_issue);
|
||||
```
|
||||
|
||||
2. **parent_issue 解析**:daemon 在 `_handle_issues` 中解析标题 `[parent #{N}]` 模式,写入 `task_state.parent_issue`(§21 §14b L920 已有此设计)。
|
||||
|
||||
3. **_check_round_complete 改造**:从扫 `tasks.parent_task`(黑板)改为扫 `task_state.parent_issue`(toolchain DB)(§21 §16.2 L1148 已有此设计)。
|
||||
1. **task_state 表创建**:已在 PR #125 中实现(`_init_task_state_table`,CREATE IF NOT EXISTS)。
|
||||
2. **parent_issue 解析**:已实现(`_ensure_task_state`,`_handle_issues` assigned 分支解析 `[parent #N]`)。
|
||||
3. **_check_round_complete 双源扫描**:已实现(`task_state.parent_issue` + `tasks.parent_task`)。
|
||||
|
||||
### 混合期处理
|
||||
|
||||
@@ -405,3 +410,115 @@ task_state 表创建前,`_check_round_complete` 仍扫 `tasks.parent_task`。
|
||||
| 5 | toolchain DB: task(review_merged) | Gitea webhook (PR closed/merged) | — | — |
|
||||
| 6 | task_state: round_count++ | task_state: parent_issue + sub status | Gitea parent Issue body + sub Issue comments | Gitea Issue comment(三问结论)+ 关闭/创建 Issue |
|
||||
| 7 | toolchain DB: task(issue_closed) | Gitea webhook (issues/closed) | — | — |
|
||||
|
||||
---
|
||||
|
||||
## §22.8 TC Round Review Gitea 适配
|
||||
|
||||
> **设计原则:三个流程已通过 Handler 架构分离(§14)。TC Round Review 的改造通过 ToolchainHandler 分流,不影响黑板流程。**
|
||||
|
||||
### 问题
|
||||
|
||||
`_check_round_complete` 中调用 `self._build_review_prompt`(黑板 API 版本),对 TC 项目也用黑板 API。但 TC 项目的协作面在 Gitea,数据源不一致。
|
||||
|
||||
### 分流方案
|
||||
|
||||
通过 Handler 架构分流,和 `_dispatch_reviews`(L1379 已有 `handler = get_by_project(); if handler: return []`)一样的模式:
|
||||
|
||||
```
|
||||
_check_round_complete:
|
||||
handler = TaskTypeRegistry.get_by_project(project_id)
|
||||
if handler and handler.virtual_project == "_toolchain":
|
||||
# TC 路径:用 Gitea API 版 review prompt
|
||||
review_prompt = handler.build_round_review_prompt(parent_id, ...)
|
||||
else:
|
||||
# 黑板路径:原有逻辑不变
|
||||
review_prompt = self._build_review_prompt(parent_task, summary, ...)
|
||||
```
|
||||
|
||||
### BaseTaskHandler 接口扩展
|
||||
|
||||
在 `BaseTaskHandler`(`task_type_registry.py`)中新增默认方法:
|
||||
|
||||
```python
|
||||
def build_round_review_prompt(self, parent_id: str, summary: dict,
|
||||
outputs: list, comments: list,
|
||||
round_num: int, **kwargs) -> str:
|
||||
"""构建 Round Review prompt。默认 raise NotImplementedError。"""
|
||||
raise NotImplementedError(
|
||||
f"{self.task_type} handler does not support round review")
|
||||
```
|
||||
|
||||
普通 task 和 mail 不调用此方法(走 ticker 原有 `_build_review_prompt`),只有 ToolchainHandler override。
|
||||
|
||||
### ToolchainHandler.build_round_review_prompt
|
||||
|
||||
TC 版本的 Round Review prompt。核心区别:
|
||||
|
||||
| 维度 | 黑板版(原) | Gitea 版(新) |
|
||||
|------|-----------|-------------|
|
||||
| Goal 来源 | `parent_task.description`(黑板 DB) | parent Issue body(庞统自己读 Gitea API) |
|
||||
| 成果物 | `bb.get_aggregate_outputs()`(黑板 DB) | PR / commit(庞统自己读 Gitea API) |
|
||||
| 讨论历史 | `bb.get_round_comments()`(黑板 DB) | Issue comments(庞统自己读 Gitea API) |
|
||||
| 创建新 sub | `POST localhost:8083/api/.../tasks`(黑板 API) | `POST Gitea /repos/.../issues`(Gitea API) |
|
||||
| 关闭 parent | 更新黑板 status | `PATCH Gitea /repos/.../issues/{N}` |
|
||||
|
||||
**prompt 设计**:只给 Issue 编号和 repo,让庞统 spawn 后自己调 Gitea API 读详情。daemon 不做 Gitea API 调用。
|
||||
|
||||
```
|
||||
## 庞统 TC Round Review(第 {round_num} 轮)
|
||||
|
||||
### Parent Issue
|
||||
- Repo: {repo}
|
||||
- Issue: #{parent_issue_number}
|
||||
|
||||
### 本轮 Sub Issue 状态
|
||||
- 完成: {done}
|
||||
- 失败: {failed}
|
||||
- 总计: {total}
|
||||
|
||||
### 你必须做什么
|
||||
|
||||
1. 读 parent Issue: GET /repos/{repo}/issues/{parent_issue_number}
|
||||
2. 读所有 sub Issue 的 comments 和 PR
|
||||
3. 三问评估:
|
||||
- Goal 还清晰吗?
|
||||
- 成果物覆盖 goal 了吗?(逐条检查 + docs/design 同步)
|
||||
- 下一轮需要做什么?
|
||||
4. 决策:
|
||||
- GOAL_ACHIEVED → 关闭 parent Issue
|
||||
- 需要新轮 → 创建新 sub Issues
|
||||
|
||||
### Gitea API
|
||||
- 读 Issue: GET /repos/{repo}/issues/{N}
|
||||
- 读 comments: GET /repos/{repo}/issues/{N}/comments
|
||||
- 创建 sub Issue: POST /repos/{repo}/issues
|
||||
- 关闭 Issue: PATCH /repos/{repo}/issues/{N} (state=closed)
|
||||
```
|
||||
|
||||
### 不影响黑板流程的保证
|
||||
|
||||
1. **Handler 分流**:`_check_round_complete` 通过 `TaskTypeRegistry.get_by_project(project_id)` 判断。普通项目(无 handler)走 `_build_review_prompt`(黑板版本不变)
|
||||
2. **数据隔离**:TC review 读 `task_state` 表 + Gitea API;黑板 review 读 `tasks` 表 + `outputs` / `comments` 表
|
||||
3. **prompt 隔离**:TC prompt 只含 Gitea API 指引;黑板 prompt 只含黑板 API 指引
|
||||
4. **`_dispatch_reviews` 已有先例**:L1379 `if handler: return []` 已经用 Handler 分流跳过 handler 项目的 review 流程
|
||||
|
||||
### 实现方案
|
||||
|
||||
| 文件 | 改动 |
|
||||
|------|------|
|
||||
| `task_type_registry.py` | `BaseTaskHandler` 加 `build_round_review_prompt` 默认方法(raise NotImplementedError) |
|
||||
| `toolchain_handler.py` | `ToolchainHandler` override `build_round_review_prompt` → 返回 Gitea API 版 prompt |
|
||||
| `ticker.py` | `_check_round_complete` 中 handler 分流:有 handler 用 handler 方法,否则用 `_build_review_prompt` |
|
||||
|
||||
### TaskState round_count 同步
|
||||
|
||||
TC 路径的 `round_count` 存在 `task_state` 表中。`_check_round_complete` 需要在 spawn review 成功后递增:
|
||||
|
||||
```python
|
||||
if handler and handler.virtual_project == "_toolchain":
|
||||
# TC 路径:递增 task_state.round_count
|
||||
conn.execute("UPDATE task_state SET round_count = round_count + 1 WHERE issue_number = ?", ...)
|
||||
else:
|
||||
# 黑板路径:原有 bb.increment_round_count(parent_id)
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user