Files
sanguo_moziplus_v2/docs/design/21-unified-toolchain-design.md
T
cfdaily 65eb7d6a99
CI / lint (pull_request) Successful in 19s
CI / test (pull_request) Successful in 1m4s
CI / frontend (pull_request) Successful in 12s
CI / notify-on-failure (pull_request) Successful in 0s
[moz] docs(§21): fix 姜维 S1 分支名前缀按 type + S2 sub Issue body 加 Depends
2026-06-20 21:24:28 +08:00

36 KiB
Raw Blame History

title, created, version, status, changelog
title created version status changelog
Unified Toolchain Design — 统一工具链工作流设计 2026-06-20 v1.0 draft draft v1.0 初版

Unified Toolchain Design

范围: 仅 toolchain 流程。task 和 mail 不变。 前置: §17 ToolchainHandler、§20 Issue-Centric Orchestration 目标: 把割裂的单点优化整合为统一的 AI native 工作流


§1. 背景与问题

1.1 当前割裂点

# 割裂 现状 本文解决
1 agent 同时引用两套 API 黑板 APIaction report/outputs+ Gitea APIIssue/PR comment §3 统一到 Gitea
2 steps 硬编码 9 处 steps=[...] 写死在 toolchain_routes.py §4 模板化
3 issue_assigned 只分 2 路 只按 infrastructure label 分流,不分 type/feat vs type/docs §5 按 type/* 6 路分流
4 action_type 和 business_type 混在一起 issue_assigned 内部混入业务场景 §6 分离两个维度
5 verify 依赖黑板 comment_type 迁移到 Gitea 后失效 §7 重新定义完成检测 + 输出约束

1.2 黑板中的"无缝接续"设计(不能丢弃)

黑板 DB 中有多个机制确保后续 agent 可以无缝接续:

机制 当前实现 用途 迁移到 Issue 后
任务描述 tasks.title + tasks.description agent 知道"做什么" Issue title + body 直接对应
验收标准 tasks.must_haves agent 知道"怎样算完成" Issue body 中结构化字段(模板定义)
前序产出 outputs 表 + depends_on agent 知道"之前做了什么" Issue body 引用前序 Issue/PR(如 Depends: #42⚠️ 需约定
handoff comment comment_type=handoff agent 之间交接上下文(≥50 字符) Issue/PR comment 天然支持
讨论历史 comments 表 agent 知道"讨论了什么" Issue/PR comment 全部可读
审查结果 reviews 表(verdict/round/consensus agent 知道"审查结论" PR ReviewAPPROVE/REQUEST_CHANGES+ Issue comment 记录
agent 声明式交接 next_capability 字段 agent 声明"我搞不定,需要 XX 能力的人" Issue comment @对方(已有 mention 机制)
retry 历史 task_attempts 表 daemon 知道"试了几次" daemon 内部 task_state 表 不变
风险观察 observations 表 agent 标记"发现风险" Issue comment(约定标记)⚠️ 需约定

结论:大部分机制可以自然迁移到 Issue。两个需要约定:

  1. 前序产出引用Issue body 中用 Depends: #NParent: #N 引用前序 Issue
  2. 风险观察Issue comment 中用约定标记(如 ⚠️ [观察]

§2. 设计原则

  1. Gitea onlytoolchain agent 只操作 Gitea,不引用黑板 API、不用 Mail
  2. 模板驱动:steps 从硬编码改为模板,不同 Issue type 对应不同流程
  3. action_type 和 business_type 分离:事件类型决定 action_hint,业务类型决定 steps
  4. 完成检测:终态事件 + 输出约束:用 Gitea 终态事件检测完成 + 结构化输出约束 agent 汇报
  5. 无缝接续不丢弃:handoff/前序产出/审查结果等机制迁移到 Issue 语义

§3. 统一到 Gitea(割裂 1 解决)

3.1 agent API 引用变更

操作 现在(黑板 API 改造后(Gitea API
提交 action report POST localhost:8083/.../comments (comment_type=action_report) POST Gitea .../issues/{N}/comments(结构化 body,§7 定义)
提交产出 POST localhost:8083/.../outputs git push 到分支(代码/文档/测试)
讨论 / @mention POST localhost:8083/.../comments POST Gitea .../issues/{N}/comments
创建 PR 已是 Gitea API(不变) 不变
创建 Issue 已是 Gitea API(不变) 不变

3.2 agent prompt 中的 API 指引

ToolchainApiSection 改造——去掉所有 localhost:8083 引用,只保留 Gitea API

## 操作指令

### 汇报执行结果
执行完步骤后,在关联的 Issue 上 comment 汇报:
```bash
curl -X POST "{GITEA}/repos/{repo}/issues/{N}/comments" \
  -H "Authorization: token <token>" \
  -d '{"body": "[Action Report]\n\n**操作**...\n**结果**...\n**CI**..."}'

需要其他角色支持

在关联的 Issue/PR 上 comment @对方(已有机制)

代码产出

git push 到功能分支 → 创建 PR


---

## §4. steps 模板化(割裂 2 解决)

### 4.1 模板存储

steps 模板存放在 daemon 配置文件 `config/toolchain-templates.yaml`

```yaml
# 每种 business_type 对应一套 steps + output_template
issue_assigned:
  feature:
    steps:
      - "理解需求(Issue body)→ 如有不明确在 Issue comment 追问"
      - "git checkout main && git pull origin main"
      - "git checkout -b fix/{issue_number}-{brief}"
      - "编码实现 + 写 UT"
      - "git add -A && git commit -m '[moz] feat: {title}' && git push"
      - "创建 PRbody 引用 IssueCloses #{issue_number}"
      - "等 CI + Review"
    output_template: |
      [Action Report]
      **分支**fix/{issue_number}-{brief}
      **PR**#{pr_number}
      **改动文件**{files}
      **CI**{ci_status}

  impl:
    steps:
      - "读设计文档(Issue body 中的路径)→ 理解实现范围"
      - "git checkout main && git pull origin main"
      - "git checkout -b impl/{issue_number}-{brief}"
      - "按设计编码实现 + 写 UT"
      - "git add -A && git commit -m '[moz] impl: {title}' && git push"
      - "创建 PRbody 引用 Issue + 设计文档路径)"
      - "等 CI + Review"
    output_template: |
      [Action Report]
      **设计文档**{design_doc}
      **分支**impl/{issue_number}-{brief}
      **PR**#{pr_number}
      **改动文件**{files}
      **CI**{ci_status}

  bug:
    steps:
      - "读 Bug 描述 + 复现步骤(Issue body"
      - "定位根因(读代码/日志,不要猜测)"
      - "git checkout main && git pull origin main"
      - "git checkout -b fix/{issue_number}-{brief}"
      - "修复 + 写回归测试"
      - "git add -A && git commit -m '[moz] fix: {title}' && git push"
      - "创建 PRbody 说明根因和修复方式)"
      - "等 CI + Review"
    output_template: |
      [Action Report]
      **根因**{root_cause}
      **修复方式**{fix_approach}
      **分支**fix/{issue_number}-{brief}
      **PR**#{pr_number}
      **CI**{ci_status}

  docs:
    steps:
      - "读文档目标(Issue body"
      - "git checkout main && git pull origin main"
      - "git checkout -b docs/{issue_number}-{brief}"
      - "编写文档到 docs/ 对应目录"
      - "git add -A && git commit -m '[moz] docs: {title}' && git push"
      - "创建 PR"
      - "等 Review"
    output_template: |
      [Action Report]
      **文档路径**{doc_path}
      **分支**docs/{issue_number}-{brief}
      **PR**#{pr_number}

  refactor:
    steps:
      - "读重构目标 + 影响范围(Issue body"
      - "git checkout main && git pull origin main"
      - "git checkout -b refactor/{issue_number}-{brief}"
      - "重构 + 确保现有测试不 breakpython -m pytest tests/unit/ -q"
      - "git add -A && git commit -m '[moz] refactor: {title}' && git push"
      - "创建 PRbody 说明重构内容和影响范围)"
      - "等 CI + Review"
    output_template: |
      [Action Report]
      **重构范围**{scope}
      **测试结果**{test_result} passed
      **分支**refactor/{issue_number}-{brief}
      **PR**#{pr_number}
      **CI**{ci_status}

  test:
    steps:
      - "读测试目标(Issue body"
      - "git checkout main && git pull origin main"
      - "git checkout -b test/{issue_number}-{brief}"
      - "编写测试脚本到 tests/ 对应目录"
      - "运行测试验证(python -m pytest {test_file} -v"
      - "git add -A && git commit -m '[moz] test: {title}' && git push"
      - "创建 PR"
      - "等 CI + Review"
    output_template: |
      [Action Report]
      **测试文件**{test_file}
      **测试结果**{test_result}
      **分支**test/{issue_number}-{brief}
      **PR**#{pr_number}

  infrastructure:
    steps:
      - "根据 Issue body 中的错误来源和日志片段排查问题"
      - "修复基础设施问题(CI runner/网络/Gitea/磁盘等)"
      - "修复后在 Issue 上 comment 说明修复方式和结果"
      - "汇报执行结果"
    output_template: |
      [Action Report]
      **问题**{problem}
      **根因**{root_cause}
      **修复方式**{fix}
      **验证**{verification}

# toolchain 事件(非 issue_assigned)的模板
ci_failure:
  steps:
    - "查看 CI 日志(PR 页面或 Gitea Actions"
    - "判断失败原因:a.代码问题→修复→push b.基础设施→创建 Issue 指派 jiangwei-infra"
    - "汇报结果"
  output_template: |
    [Action Report]
    **原因类型**{cause_type}
    **操作**{action}
    **CI 重跑**{ci_status}

# ... 其他 toolchain 事件(review_result/review_request/...)各自定义

4.2 模板加载

daemon 启动时加载 YAML 配置,运行时按 action_type + business_type 查找模板:

def get_steps(action_type: str, business_type: str = "") -> list[str]:
    """从模板配置获取 steps"""
    section = TEMPLATES.get(action_type, {})
    if isinstance(section, dict) and business_type:
        return section.get(business_type, {}).get("steps", section.get("default", {}).get("steps", []))
    return section.get("steps", [])

§5. 按 type/* 6 路分流(割裂 3 解决)

5.1 issue_assigned handler 改造

当前只按 infrastructure label 分 2 路。改为按 type/* label 分流:

# 伪代码
labels_list = [lbl.get("name", "") for lbl in (issue.get("labels") or [])]

# 1. 基础设施(不变)
if any("infrastructure" in lbl.lower() for lbl in labels_list):
    business_type = "infrastructure"
# 2. 按 type/* 确定 business_type
elif "type/feat" in labels_list:
    business_type = "feature"
elif "type/impl" in labels_list:
    business_type = "impl"
elif "type/bug" in labels_list:
    business_type = "bug"
elif "type/docs" in labels_list:
    business_type = "docs"
elif "type/refactor" in labels_list:
    business_type = "refactor"
elif "type/test" in labels_list:
    business_type = "test"
else:
    business_type = "feature"  # 默认走编码流程

# 从模板获取 steps + output_template
template = get_template("issue_assigned", business_type)
steps = template["steps"]
output_template = template["output_template"]

5.2 action_hint 差异化

当前 action_hint 按 action_type 固定("你收到一个 Issue 指派...")。改为同时体现 business_type

_ACTION_HINTS = {
    "issue_assigned": {
        "feature": "你收到一个功能需求,理解需求后编码实现。",
        "impl": "你收到一个实现任务,按设计文档编码实现。",
        "bug": "你收到一个 Bug 报告,定位根因后修复。",
        "docs": "你收到一个文档任务,编写文档。",
        "refactor": "你收到一个重构任务,重构并确保测试通过。",
        "test": "你收到一个测试任务,编写测试脚本。",
        "infrastructure": "你收到一个基础设施问题报告,请排查并修复。",
    },
    "ci_failure": "你收到一个 CI 失败通知,这是一个需要你修复失败测试的事件。",
    "review_result": "你收到一个 Review 结果通知,这是一个需要你执行动作的事件。",
    # ... 其他 action_type 不分 business_type
}

§6. action_type 和 business_type 分离(割裂 4 解决)

6.1 两个维度

维度 来源 决定什么 示例
action_type webhook 事件类型 action_hint"你收到一个 XX 通知" ci_failure / review_result / issue_assigned
business_type Issue label type/* steps + output_template feature / impl / bug / docs / refactor / test

6.2 组合规则

  • issue_assignedaction_type=issue_assigned + business_type 从 label 确定
  • ci_failureaction_type=ci_failure(无 business_typeCI 失败就是 CI 失败)
  • review_resultaction_type=review_result(无 business_typeReview 就是 Review
  • 只有 issue_assigned 需要 business_type 维度(因为同一个 action_type 下不同业务的流程不同)

§7. 完成检测 + 输出约束(割裂 5 解决)

7.1 设计原则

关注点 方案
完成检测 Gitea 终态事件优先 + Issue comment 兜底
输出约束 按 business_type 定义的 output_template(不是空泛的"简要描述")

7.2 完成检测:按 action_type 分类

action_type 终态信号 检测方式 兜底
issue_assigned PR merged 或 Issue closed webhook: pull_request/closed(merged=true) 或 issues/closed
ci_failure agent Issue comment 汇报 Issue comment 检测([Action Report] 标记) ⚠️ Gitea 1.26.2 不触发 CI status webhook,只能靠 comment 兜底。ticker 可选轮询 Gitea commit status API 作为补充
review_result(APPROVED) PR merged webhook: pull_request/closed(merged=true)
review_result(CHANGES) agent push 到分支 webhook: pull_request/synchronize
review_request Review 提交 webhook: pull_request_review
review_updated Review 提交 webhook: pull_request_review
review_comment agent comment webhook: issue_comment/created
mention agent comment webhook: issue_comment/created
deploy_failure agent Issue comment 汇报 Issue comment 检测
infrastructure_failure agent Issue comment 汇报 Issue comment 检测
review_merged auto-pass

7.3 状态流转:单一终态保证

一个 task 只有一个终态触发。daemon 内部状态机保证:

pending → working → done(终态事件触发,只触发一次)
                   → failed(超时/异常)

终态事件到来时检查 task 当前状态:

  • 如果已经 done/failed → 忽略(幂等)
  • 如果 working → 标 done
  • 如果 pending → 异常,记日志

中间事件push/comment/Review submitted不改变 task 状态——它们是过程中的信号,不是终态。

7.4 输出约束:output_template

每种 business_type 有自己的 output_template(§4.1 定义)。agent 完成后在 Issue comment 中按模板汇报。

daemon 的 verify 通过 webhook 事件检测终态(不需要检查 comment 内容)。但 output_template 的价值是约束 agent 的汇报质量——不是检测完成用的,而是给后续 agent/审查者提供结构化信息。

output_template 作为 steps 的最后一步注入 prompt

7.5 action report 识别规范

daemon 通过 webhook issue_comment/created 感知到新 comment 后,需要判断是否为 action report。

匹配规则

  • 精确匹配:comment body 以 [Action Report] 开头(允许前导空白)
  • 容错策略:如果 body 包含 [Action Report](不要求开头),也接受
  • 大小写不敏感

匹配失败处理

  • 不匹配的 comment 不触发完成检测
  • 作为普通讨论 comment 处理(agent 之间的 handoff/讨论)
最后一步:汇报执行结果,在 Issue 上 comment,格式:
[Action Report]
**根因**<根因描述>
**修复方式**<做了什么>
**分支**fix/42-xxx
**PR**#43
**CI**:✅ 通过

§8. 无缝接续机制迁移

8.1 前序产出引用

当前黑板用 depends_on 字段 + PriorOutputsSection 注入前序产出摘要。

迁移到 Issue 后,在 Issue body 中用约定引用:

## 依赖
Depends: #42(前序任务)
Parent: #40(父 Issue

## 前序产出摘要
- #42 完成了数据获取模块(分支 fix/42-dataPR #43
- 数据路径:/Volumes/stock/xxx

agent 读 Issue body 自然获得前序上下文。daemon 的 spawner 在构建 prompt 时,可以解析 Issue body 中的 Depends: #N,调 Gitea API 读取前序 Issue 的 comment(包含 action report)作为上下文注入。

8.2 handoff comment

当前 handoff 通过黑板 comment_type=handoff + ≥50 字符约束。

迁移到 Issue 后,agent 的 handoff 就是Issue/PR comment。不需要 comment_type 字段——所有有实质内容的 comment 都是为后续 agent 提供上下文的"handoff"。

8.3 审查结果

当前黑板 reviews 表存 verdict/round/consensus。

迁移后:

  • 代码审查PR ReviewGitea 原生,APPROVE/REQUEST_CHANGES
  • 方案审查(设计 PR):同上
  • 庞统 round review:保留在 daemon 内部(不迁移,这是编排逻辑)

§9. prompt 层级(L0-L4 不变,L2 重组)

内容 不变?
L0 铁律 安全底线 不变
L1 角色 SOUL.md / IDENTITY.md 不变
L2 引擎注入 本文重组 改造
L3 被参考 Skill 列表 不变

L2 重组后的 section 列表:

priority Section 内容 来源
10 ToolchainContextSection action_hint + Issue body(需求)+ steps 改造:从模板加载 steps
20 PriorContextSection 前序产出(解析 Issue body 中的 Depends 改造现有 PriorOutputsSection
30 RoleSkillSection 角色 Skill 不变
35 GitOperationSection Git 操作说明(PR #95 已有) 不变
40 GiteaApiSection Gitea API 指引(Issue comment + PR 创建) 改造:去掉黑板 API
50 ToolchainConstraintsSection 约束 + Red Flags 不变
55 GiteaConventionSection Gitea 标题规范 不变
60 WikiGuideSection 知识查询引导 不变
65 DeliveryChecklistSection 交付检查 改造:output_template 替代空泛的"简要描述"

§10. 涉及改动

文件 改动 工作量
config/toolchain-templates.yaml 新建:6 种 business_type steps + output_template 新文件
src/daemon/toolchain_handler.py ToolchainApiSection 改为 GiteaApiSection(去黑板 API);action_hint 支持 business_type 改造
src/daemon/toolchain_handler.py verify_completion 改为终态事件检测 + Issue comment 兜底 改造
src/api/toolchain_routes.py issue_assigned handler 按 type/* 6 路分流 改造
src/api/toolchain_routes.py steps 从模板加载(替代硬编码) 改造
src/daemon/toolchain_handler.py webhook handler 增加终态事件检测 新增
.gitea/ISSUE_TEMPLATE/ 新增 impl.yml / docs.yml / refactor.yml 新文件
tests/ 更新测试 改造

§11. Issue closed 事件处理

11.1 问题

当前 _handle_issues 只处理 action == "assigned",不处理 action == "closed"。Issue 被关闭时:

  • daemon 不感知(webhook issues/closed 被忽略)
  • 创建者 / 关注者收不到通知
  • 如果该 Issue 对应一个活跃的 taskdaemon 不知道 Issue 已关闭

11.2 设计

_handle_issues 增加 action == "closed" 分支:

谁被通知Issue 创建者(issue.user.login)。

通知内容(通过 toolchain task 发给创建者):

  • Issue 标题 + 编号
  • 关闭者(payload.sender.login
  • 关闭时间
  • Issue 上最后一个 comment 的摘要(修复说明)

通知类型:纯通知(event_type=issue_closedverify auto-pass,和 review_merged 一样)。

特殊情况

  • 如果关闭者是创建者自己(自己关自己创建的),不通知(避免自环)
  • 如果 Issue 没有创建者信息或创建者不是已知 agent,跳过

11.3 实现伪代码

# _handle_issues 中新增
if action == "closed":
    issue_creator = issue.get("user", {}).get("login", "")
    closed_by = payload.get("sender", {}).get("login", "")
    
    # 自己关自己创建的,不通知
    if issue_creator == closed_by:
        return
    
    # 只通知已注册的 agent
    if issue_creator not in AGENT_IDS:
        return
    
    # 读取最后一个 comment 作为修复摘要
    comments = issue.get("comments", 0)
    last_comment_summary = "(无 comment)"
    # 可选:调 Gitea API 读最后一个 comment
    
    title = f"Issue 已关闭: {issue_title} ({repo}#{issue_number})"
    description = f"Issue {repo}#{issue_number} 已被 {closed_by} 关闭。\n\n{last_comment_summary}"
    
    _send_toolchain_task(
        to_agent=issue_creator,
        title=title,
        description=description,
        event_type="issue_closed",
        action_type="issue_closed",
        steps=[],  # 纯通知,无步骤
        context_data={
            "issue_number": issue_number,
            "repo": repo,
            "issue_title": issue_title,
            "closed_by": closed_by,
        },
    )

11.4 _ACTION_HINTS 新增

"issue_closed": "你创建的 Issue 已被关闭。这是一条纯通知,阅读即可。",

11.5 EVENT_LABELS_ZH 新增

"issue_closed": "Issue 已关闭",

11.6 verify_completion

issue_closed 走 auto-pass(和 review_merged 一样),纯通知不需要 agent 动作。

11.7 涉及改动

文件 改动
src/api/toolchain_routes.py _handle_issues 新增 action == "closed" 分支
src/daemon/toolchain_handler.py _ACTION_HINTS 新增 issue_closed
src/daemon/toolchain_handler.py EVENT_LABELS_ZH 新增 issue_closed
src/daemon/toolchain_handler.py verify_completion issue_closed auto-pass
templates/toolchain/issue_closed.md 新建通知模板
tests/ 新增 closed 事件测试

§12. AI Native 能力完整性(v2 补充)

本节确保 Gitea 替代黑板后,PRD-v3.0 的 AI native 能力不降级。 对照 §01 四相循环实现 + spawner.py / ticker.py / operations.py 的实际代码逐项检查。

12.1 完整能力对照表

# AI native 能力 黑板实现 Gitea Issue 对应 保留? §21 补充
1 Discussion 讨论 spawner DISCUSSION_PROMPT_TEMPLATE + spawn_type=discussion + ticker 广播 parent Issue 创建后 ticker 广播 spawn discussion promptIssue comment 是讨论空间 §13
2 Agent 自建 sub agent POST /tasks {parent_task, must_haves} agent POST Gitea /issues {title: "[repo][sub][parent #N] ..."} + assign 自己 §14
3 @mention 通知 comment mentions 字段 → mention_queue → ticker 扫描 → spawn 被@者 Gitea Issue/PR comment @ → webhook issue_comment → daemon 解析 @ → spawn §15
4 Round review _check_round_complete → parent sub 全终态 → spawn 庞统三问 daemon 扫 task_state parent 下所有 sub 终态 → spawn 庞统 review §16
5 Retry 上下文 retry_count 字段 + _build_retry_context task_state.retry_count + retry prompt(不变) 不需额外
6 Handoff comment comment_type=handoff + ≥50 字符 Issue/PR comment(无 type 区分,但 Boids 行为准则约束 agent 写实质内容) §17
7 Outputs 产出物 outputs 表 {agent, type, content_path, summary} 分支 commit(代码/文档)+ Issue comment(摘要) 不需额外
8 Depends_on 前序 tasks.depends_on 字段 + PriorOutputsSection Issue body Depends: #N + daemon 解析注入 §17
9 Boids 行为准则 DISCUSSION_PROMPT 中的 4 条准则 discussion prompt 不变(Boids 准则在 prompt 中,与存储介质无关) §13
10 Agent 自主涌现 无 assignee 的 parent task → ticker 广播 → agent 自主讨论/创建 sub 无 assignee 的 parent Issue → ticker 广播 discussion → agent 自建 sub Issue §13/§14
11 Guardrail 安全红线 dispatcher check_task → violations → block 不变(guardrail 查 task_state,不依赖黑板) 不需额外
12 Classify outcome spawner _classify_outcome → done/failed/pending 不变(classify 逻辑在 daemon 内部) 不需额外
13 Rebuttal review.py submit_rebuttal → @mention assignee + 回到 working PR Review REQUEST_CHANGES → webhook → daemon 通知 agent 不需额外
14 Checkpoints checkpoint_routes.py → approve/reject PR Review(代码/方案审查统一走 PR Review) 不需额外

12.2 结论

14 项 AI native 能力全部可保留。 其中需要补充设计的是 5 项(§13-§17),其余沿用现有 daemon 逻辑不变。


§13. Discussion 能力保留

13.1 设计

庞统创建 parent Issue(无 assignee)后,触发 discussion

庞统创建 parent Issue → webhook: issues/assigned(或 ticker 发现 pending 无 assignee
  → daemon 检测:无 assignee = 广播讨论
  → ticker 广播 spawn 所有 agentspawn_type=discussion
  → 每个 agent 收到 DISCUSSION_PROMPT_TEMPLATE

13.2 Discussion Prompt 设计(v3 重构)

设计参考:Edict(角色驱动主动发言)+ APM(自包含 Task Prompt+ PAV 循环(输入/输出/验证)。

当前问题:DISCUSSION_PROMPT 只列了"你可以做什么",没引导 agent 思考"我和这个需求什么关系"。agent 读完和自己没关系就忽略了。

重构后 discussion prompt

你被 spawn 来参与 Gitea Issue 讨论。这是一个四相循环的讨论环节。

## 讨论主题
{parent Issue body 全文}

## 你是谁
你是 {agent_id}{display_name}),你的角色是 {role},你的专业能力是 {capabilities}。
(如:你是 zhangfei-dev(张飞 翼德),角色是编码先锋,能力是编码/脚本/实现)

## 你必须做什么

读完需求后,在 Issue 上 comment 回应(必须,不是可选):

1.【定位】这个需求和你有什么关系?你的专业能力能贡献什么?
2.【建议】你对实现方案有什么建议?(技术选型、数据来源、实现路径)
3.【认领】如果你需要参与,创建 sub Issue 并在 parent Issue comment 注册:
   - 创建 sub IssuePOST /repos/{repo}/issues
     title: "[repo][sub][parent #{N}] 任务名"
     body: "Parent: #{N}\nDepends: #M (如果有前序依赖)\n## 任务\n..."
     assignees: ["{你的 agent_id}"]
   - 创建后在 parent Issue comment"[{你的角色名}] 我创建了 sub #{M}: {任务名},我负责 {简述}"
4.【风险】如果你发现风险、不合理的假设、或遗漏的环节,直接提出

⚠️ 每个 agent 必须 comment。即使你认为和自己无关,也要说明原因——这证明你读过并思考过了。不 comment 的 agent 会被视为未参与讨论。

## Comment 格式
你的 comment 必须以角色名开头,让其他人知道你是谁:
[{角色名}] {你的观点}
例:[张飞] 我来负责策略编码,用 vnpy CtaTemplate 实现。
例:[关羽] 这个策略需要风控,连亏 3 天应暂停。
例:[赵云] 数据已就绪,2024-08 缺失已补齐。
例:[姜维] 我与此需求无直接关系,但建议关注回测滑点设置。

## APIGitea
- 读 Issue 详情+commentsGET /repos/{repo}/issues/{N}
- 写 commentPOST /repos/{repo}/issues/{N}/comments
- 创建 sub IssuePOST /repos/{repo}/issues

## 行为准则
1. 你是自主的。读 Issue、思考、行动,不要等指令。
2. 不重复别人的工作。动手前先读 Issue comments 看谁在做什么(Separation)。
3. 保持方向对齐。你的产出方向和 parent goal 对齐,不确定时 @pangtong-fujunshiAlignment)。
4. 产出可共享。产出写入 Issue comment,让其他人能看到你的成果(Cohesion)。
5. 不越界。安全红线不要碰,超出能力的 @ 庞统升级(Boundary)。
6. 随时讨论。执行过程中需要协作时 @ 对应 Agent,讨论是灵活的不是固定阶段的。

与现有实现差异

  1. 新增"你是谁"段——agent 知道自己的角色和能力,有定位感
  2. 新增"你必须做什么"——4 条必须回应的维度,不是可选
  3. 新增 comment 格式——以角色名开头,其他人知道是谁在说
  4. 新增"创建 sub 后在 parent comment 注册"——parent Issue comment 流自然包含所有 agent 的表态和分工
  5. 底线约束:不 comment = 未参与——强制每个 agent 思考和表态

输入/输出/验证标准PAV 循环):

阶段 输入 输出 验证
Discussion parent Issue bodygoal 每个 agent 的 comment(定位+建议+认领+风险) 所有被 spawn 的 agent 都 comment 了

13.3 庞统初始引导

庞统创建 parent Issue 时,可以在 Issue body 中 @ 特定 agent 引导认领:

Issue body:
  ## 任务
  做一个双均线量化策略...
  
  ## 建议分工
  @zhangfei-dev 你来认领策略编码
  @zhaoyun-data 你来认领数据准备

但庞统不需要知道全部——关羽可能发现需要风控,自己创建 sub 去做。司马懿可能发现需要测试,自己创建 sub。这是涌现,不是分配。

13.4 Parent Issue 中的 sub 注册

agent 创建 sub Issue 后,自己在 parent Issue 上 comment 注册(不需要 daemon 做):

[张飞] 我创建了 sub #101: 策略编码,我来负责实现。
技术方案:用 vnpy CtaTemplate,金叉买入死叉卖出。

Gitea 的 Issue reference 功能会自动在 parent Issue timeline 显示 "Referenced by #N"。 agent 的 comment + Gitea 自动引用 = parent Issue 中有完整的 sub 注册信息。

13.5 分支创建时机

阶段 谁创建分支? 分支名
DiscussionPhase 3 不创建分支
ExecutorPhase 4 agent 收到 executor prompt 后自己创建 {type}/{sub_issue_number}-{brief}type 按 Issue 类型:fix/feat/impl/docs/refactor/test

executor prompt 的 steps 中明确指定分支名

git checkout -b fix/{issue_number}-{brief}

多分支并行场景(每个 sub Issue number 不同,分支名不同,不冲突):

张飞 sub #101 → 分支 fix/101-dual-ma-strategy
关羽 sub #102 → 分支 fix/102-risk-control
司马懿 sub #103 → 分支 fix/103-strategy-test

13.6 L2 输入输出约束(PAV 循环)

每种 prompt 都有明确的输入/输出/验证标准:

prompt 类型 输入 输出 验证
Discussion parent Issue bodygoal 每个 agent comment(定位+建议+认领+风险) 所有 spawn 的 agent 都 comment 了
Executor sub Issue body + parent Issue body + 所有 comments [Action Report](分支+PR+改动+CI PR 创建 + CI 通过
Review(司马懿) PR diff + sub Issue body + parent goal Review verdictAPPROVE/REQUEST_CHANGES Review API 提交
Round Review(庞统) parent Issue body + 所有 sub outputs + 所有 comments 三问评估(goal 一致性/成果覆盖/下一步) GOAL_ACHIEVED 或新轮 sub

§14. Agent 自建 sub Issue 模式

14.1 设计

替代当前的 claim 竞争模式。每个 agent 自己创建 sub Issue + assign 自己。

标题格式

[quant][sub][parent #100] 策略编码
  • [quant] — 项目代号
  • [sub] — 标记为 sub Issue
  • [parent #100] — parent Issue 编号(Gitea 自动渲染 #100 为链接)
  • 后面是人类可读的任务描述

Sub Issue body

Parent: #100

## 任务
从 parent Issue 继承的具体任务描述

## 验收标准
...

Gitea 的 Issue reference 功能会自动在 parent Issue #100 上显示 "Referenced by #101"。

14.2 不需要 claim 竞争

当前黑板的 claim 模式(CAS 原子操作)是为了防止两个 agent 认领同一个 task。

在 Gitea Issue 模式下,每个 agent 创建自己的 sub Issue——不存在竞争。各创建各的,各 assign 各的。

重复不怕:如果关羽和张飞创建了内容重叠的 sub Issue,庞统在 round review 时引导两人统一看法。这不是错误,是讨论的契机。不做严谨工作流,做 AI 生态。

14.3 daemon 内部 parent/sub 映射

daemon 维护 parent/sub 层级(用于 round review 检测):

-- task_state 表(§20 设计)
CREATE TABLE task_state (
    issue_number INTEGER,
    repo TEXT,
    parent_issue INTEGER,    -- 新增:parent Issue 编号
    status TEXT DEFAULT 'pending',
    ...
);

daemon 监听 Issue 创建 webhook → 解析标题中的 [parent #N] → 记录 parent_issue。

⚠️ 需同步更新 §20 task_state DDL 新增 parent_issue INTEGER 列。


§15. @mention 通知迁移

15.1 当前实现

agent 写 comment → mentions 字段 → mention_queue 表 → ticker 扫描 → spawn 被@者

15.2 Gitea 迁移

agent 写 Issue/PR comment → webhook: issue_comment/created → daemon 解析 @ → spawn 被@者

mention_queue 表保留,但数据来源改为 webhook payload。daemon 收到 issue_comment webhook 后:

  1. 正则提取 comment body 中的 @( [- ]*)
  2. 写入 mention_queue
  3. ticker 消费 mention_queue → spawn 被@者

复用现有 mention_utils.py 的 extract_mentions 逻辑(§25 已实现)。


§16. Round Review 迁移

16.1 当前实现

ticker._check_round_complete

  1. 扫描所有 parent task
  2. 检查 sub task 是否全部终态
  3. spawn 庞统 review(三问框架)

16.2 Gitea 迁移

ticker._check_round_complete 改为:

  1. 扫描 task_state 中 parent_issue IS NOT NULL(替代原 SELECT DISTINCT parent_task FROM tasks,语义不变——都是找有子任务的 parent)
  2. 找到所有 parent_issue 相同的 sub Issue
  3. 检查 sub Issue 是否全部终态(通过 task_state.status
  4. 全部终态 → spawn 庞统 review

庞统三问 prompt 不变

1. Goal 还清晰吗?(是否有 goal drift)
2. 成果物覆盖 goal 了吗?(逐条检查验收标准)
3. 下一轮需要做什么?(创建新 sub / 标记完成 / 调整方向)

庞统通过 Gitea API 读 parent Issue bodygoal+ 所有 sub Issue 的 comments/outputs → 做评估。


§17. 无缝接续机制完整迁移

17.1 handoff comment

当前:comment_type=handoff + ≥50 字符

Gitea:所有 Issue/PR comment 都是天然的 handoff。Boids 行为准则约束 agent 写实质内容。不强制 ≥50 字符——用 Boids 准则引导比硬阈值更 AI native。

17.2 depends_on 前序引用

当前:tasks.depends_on 字段 + PriorOutputsSection

GiteaIssue body 中 Depends: #N。daemon 解析 → 读前序 Issue 的 comments(含 Action Report)→ 注入 prompt。

17.3 retry 上下文

currentretry_count 字段 + _build_retry_context

Giteatask_state.retry_count(不变,daemon 内部)。retry prompt 中加入前序 Issue/PR 链接供 agent 参考。

17.4 状态转换流转

agent 完成后的状态转换(working → review → done)全部由 daemon 内部管理。agent 不需要手动 POST status。daemon 通过以下信号自动感知:

信号 来源 触发
agent 创建 sub Issue webhook: issues/opened sub status=pending → dispatch
agent 创建 PR webhook: pull_request/opened sub status → review
PR Review 提交 webhook: pull_request_review review 结果 → done 或 back to working
PR merge webhook: pull_request/closed(merged) sub status → done + Issue auto-close
agent Issue comment webhook: issue_comment/created 检查是否为 Action Report → 终态检测

§18. 不做的事

不做 理由
不改 task handler task 流程不变(§20 设计中的 task 逐步迁移到 Issue 是后续工作)
不改 mail mail 职责不变
不改 dispatcher/ticker 核心逻辑 调度逻辑不变(§20 Phase 1 的 dispatcher SQL 迁移是前置工作)
不做前端改造 后续独立设计
不改 experiences/checkpoints/decisions 表 执行面表保留在 daemon