Files
sanguo_moziplus_v2/docs/design/19-toolchain-context-layers.md
T
cfdaily 149921fb5f
CI / lint (push) Successful in 7s
CI / test (push) Successful in 14s
CI / lint (pull_request) Successful in 7s
CI / notify-on-failure (push) Successful in 0s
CI / test (pull_request) Successful in 14s
CI / notify-on-failure (pull_request) Successful in 0s
docs: add #19 toolchain context layers design
2026-06-09 22:25:17 +08:00

13 KiB
Raw Blame History

#19 工具链事件中枢 — 上下文四层改造方案

版本: v1.0 日期: 2026-06-09 作者: 庞统(副军师) 状态: 待主公确认 前置: #13 工具链与开发流程 §16, #05 上下文四层架构 来源: E2E 真实场景测试暴露的三个断层


一、问题诊断

1.1 E2E 真实场景测试暴露的三个断层

主公在 moziplus-v2 仓库创建了 Issue #32(添加 /api/stats 端点),指派张飞。链条在第一步就断了。

断层 现象 根因
Agent 不知道该做什么 张飞收到 Issue 指派 Mail,回复"已阅"就结束了 Mail 模板(issue_assigned.md5 行信息,无流程引导;spawn prompt 说"已阅即可"
Agent 去错了仓库 张飞去读了 sanguo_moziplus_v2 平台代码,而不是空的实验仓库 moziplus-v2 Mail 模板没有仓库 clone URL,张飞凭习惯去了开发目录
Agent 在 Control UI 提问 张飞遇到问题直接在 Control UI 问主公,没有去 Gitea Issue 评论 没有任何地方引导"有疑问去 Gitea Issue 评论"
Agent 不知道怎么协作 张飞判断任务需要澄清,但不知道该怎么请求澄清 没有"做不了→在 Issue 评论 / Mail 庞统"的回退路径
跨 Agent @mention 无法通知 张飞在 Issue 评论 @赵云,赵云收不到通知 issue_comment handler 只处理 [CI] 评论,@mention 被忽略

1.2 根因:工具链在四层架构中的断层

应该有 实际有 Gap
L0 铁律 无需改动
L1 角色 工具链协作行为规范(所有 Agent 共享) AGENTS.md 没有工具链相关内容
L2 引擎注入 事件上下文(仓库 clone URL、Gitea API、Issue/PR 详情) Mail 模板只有 5 行摘要 缺仓库信息和流程引导
L3 被动参考 技术细节(分支命名、commit 规范、PR 创建方式) git-workflow 等 Skill 已存在但没人触发 Agent 不知道该加载哪个 Skill

二、改造方案:四层归属

2.1 分层原则

放什么 不放什么 理由
L0 不放 工具链不是安全底线
L1 协作行为规范:收到什么通知该做什么、遇到问题怎么办 技术细节(分支命名、commit 格式) 行为规范是团队常识,每个 Agent 都要知道
L2 事件上下文:仓库 clone URL、Gitea API URL、Issue/PR 链接、动态信息 固定的协作流程 动态信息每次不同,由 Mail 模板 + spawn 时注入
L3 技术细节:git-workflow、code-review 等 Skill 全文 按需加载,Agent 知道"我要提 PR"后自己读

2.2 各层具体内容

L1AGENTS.md 加工具链协作行为段(所有 Agent 统一)

## 工具链协作(Gitea

收到 Gitea 事件通知(Issue 指派、Review 请求、CI 失败等)时,按以下流程操作:

### 基本流程
- **Issue 指派** → clone 仓库 → 开分支 → 编码 → 提 PR(参考 git-workflow Skill
- **Review 请求** → 读 PR diffGitea API)→ 提交 Review(参考 code-review Skill
- **Review 通过** → 等 merge
- **Review 驳回** → 看 review body → 修代码 → 重新 push
- **CI 失败** → 看错误摘要 → 修代码 → push(自动重触发 CI)
- **部署失败** → 查 deploy 日志 → 修复

### 协作规则
- **有疑问?** 在 Gitea Issue 下评论,不要在 Control UI 或 Mail 里问
- **需要别人帮忙?** 在 Issue 评论中 @mention 对应 Agent(如 @zhaoyun-data
- **做不了?** 回复 Mail 说明原因和建议的接手人
- **获取完整上下文** → 用 Gitea API 拉取 Issue 详情和评论,不要只看 Mail 里的快照

### Gitea API 速查
- Issue 详情: GET /api/v1/repos/{owner}/{repo}/issues/{number}
- Issue 评论: GET /api/v1/repos/{owner}/{repo}/issues/{number}/comments
- PR diff: GET /api/v1/repos/{owner}/{repo}/pulls/{number}.diff
- 提交 Review: POST /api/v1/repos/{owner}/{repo}/pulls/{number}/reviews

改动范围6 个 Agent 的 AGENTS.md 各加一段(内容统一)。

L2:Mail 模板精简 + 事件上下文注入

原则:模板只放摘要 + 链接 + 仓库信息,不写固定步骤(步骤在 L1)。

issue_assigned.md 改为:

Issue 指派

Issue: {issue_url}
标题: {issue_title}
标签: {labels}

📋 获取完整上下文(先读再动手):
- Issue 详情: GET {gitea_api}/repos/{repo}/issues/{issue_number}
- Issue 评论: GET {gitea_api}/repos/{repo}/issues/{issue_number}/comments

仓库: {repo_clone_url}
建议分支: feat/issue-{issue_number}-{brief}

review_request.md 改为:

PR Review 请求

PR: {pr_url}
标题: {pr_title}
作者: {pr_author}
分支: {branch}
风险级别: {risk_level}

📋 获取完整上下文:
- PR diff: GET {gitea_api}/repos/{repo}/pulls/{pr_number}.diff
- PR 文件列表: GET {gitea_api}/repos/{repo}/pulls/{pr_number}/files

review_result.md 改为:

Review {result}

PR: {pr_url}
标题: {pr_title}
审查者: {reviewer}

{review_body}

ci_failure.md 改为:

CI 失败

Issue: {issue_url}
分支: {branch}

错误摘要:
{error_summary}

📋 CI 日志: {gitea_url}/{repo}/actions
修复后 push 会自动重触发 CI。

deploy_failure.md 改为:

部署失败

仓库: {repo}
Commit: {commit_sha}

📋 排查步骤:
- CI 日志: {gitea_url}/{repo}/actions
- 服务器: pm2 logs {service_name}

L2 代码改动toolchain_routes.py):

  1. 从 Webhook payload 的 repository 对象提取 clone_urlhtml_url
  2. render_template() 传入新变量:gitea_apigitea_urlrepo_clone_url
  3. 所有模板变量统一补齐

L3Skill 按需加载(不改 Skill 本身)

git-workflow、code-review 等 Skill 保持不变。

L1 的协作行为段里会引用 Skill 名称("参考 git-workflow Skill"),Agent 收到 Mail 后根据 L1 的引导自主加载对应 Skill。

不改 Skill 路由机制——靠 L1 的文案触发 Agent 的 Skill 路由器匹配。


三、新增功能:issue_comment @mention 通知

3.1 设计

当前 _handle_issue_comment 只处理 [CI] 前缀评论。扩展为:

issue_comment 事件
  ├── 含 [CI] / CI 失败 → 原有 CI 失败通知逻辑
  └── 含 @username → 解析 @mention → Mail 通知被 @的 Agent

3.2 实现

toolchain_routes.py 新增 _handle_issue_comment_mention()

AGENT_IDS = {
    "zhangfei-dev", "guanyu-dev", "zhaoyun-data",
    "jiangwei-infra", "simayi-challenger", "pangtong-fujunshi",
}

# 前缀映射:@张飞 → zhangfei-dev
AGENT_ALIAS = {
    "张飞": "zhangfei-dev",
    "关羽": "guanyu-dev",
    "赵云": "zhaoyun-data",
    "姜维": "jiangwei-infra",
    "司马懿": "simayi-challenger",
    "庞统": "pangtong-fujunshi",
    "pangtong": "pangtong-fujunshi",
    "simayi": "simayi-challenger",
    "zhangfei": "zhangfei-dev",
    "guanyu": "guanyu-dev",
    "zhaoyun": "zhaoyun-data",
    "jiangwei": "jiangwei-infra",
}

def extract_mentions(body: str, sender: str) -> list[str]:
    """从评论 body 中提取 @mention 的 Agent ID"""
    candidates = re.findall(r"@([a-zA-Z\u4e00-\u9fa5][a-zA-Z0-9\u4e00-\u9fff-]*)", body)
    result = set()
    for c in candidates:
        # 精确匹配
        if c in AGENT_IDS:
            result.add(c)
        # 前缀/别名匹配
        elif c in AGENT_ALIAS:
            result.add(AGENT_ALIAS[c])
        else:
            # 前缀模糊匹配:@zhangfei → zhangfei-dev
            for aid in AGENT_IDS:
                if aid.startswith(c):
                    result.add(aid)
                    break
    # 过滤掉评论者自己
    result.discard(sender)
    return list(result)

新增 mention 通知模板 templates/toolchain/mention.md

你在 Issue 中被 @mention

Issue: {issue_url}
评论者: {commenter}
评论内容:
{comment_body}

📋 获取完整上下文:
- Issue 详情: GET {gitea_api}/repos/{repo}/issues/{issue_number}
- Issue 评论: GET {gitea_api}/repos/{repo}/issues/{issue_number}/comments

改动 _handle_issue_comment

async def _handle_issue_comment(payload):
    comment = payload.get("comment", {})
    body = comment.get("body", "")
    sender = comment.get("user", {}).get("login", "")
    repo = _repo_fullname(payload)
    issue = payload.get("issue", {})

    # 原有 CI 失败逻辑(不变)
    if "[CI]" in body or "CI 失败" in body:
        # ... 原有逻辑 ...

    # 新增:@mention 通知
    mentions = extract_mentions(body, sender)
    if mentions:
        issue_number = issue.get("number", 0)
        issue_title = issue.get("title", "")
        text = render_template("mention", {
            "repo": repo,
            "issue_number": str(issue_number),
            "issue_url": issue.get("html_url", ""),
            "commenter": sender,
            "comment_body": body[:500],
            "gitea_api": "http://192.168.2.154:3000/api/v1",
        })
        title = f"@mention: {issue_title} ({repo}#{issue_number})"
        for agent_id in mentions:
            _send_mail(agent_id, title, text)

3.3 去重

  • 同一条评论 @多人:每人一封 Mail(不同 to,内容相同)
  • 同一事件 org webhook + repo webhook 双触发:现有 delivery UUID 去重机制覆盖
  • 同一人被 @多次:extract_mentions 返回 set,自动去重

四、Mail Spawn Prompt 改造

4.1 问题

当前工具链 Mail 走 Mail 通道,spawn prompt 是:

你收到一封飞鸽传书(纯通知)。
发件者: system
主题: Issue 指派: xxx
内容: [工具链模板]
已阅即可。

"已阅即可"直接让 Agent 不做事。

4.2 方案

不改 MAIL_INFORM_TEMPLATE / MAIL_REQUEST_TEMPLATE 本身(那是 Mail 系统通用的)。

改为:工具链 Mail 使用 type=request(而不是默认的 inform

_send_mail() 中,工具链事件创建的 Mail 默认 performative=request,这样 Agent 收到时走 MAIL_REQUEST_TEMPLATE,知道需要处理。

具体改动在 _send_mail() 函数或其调用处:工具链路由调用 _send_mail 时传入 performative="request"


五、完整改动清单

# 改什么 改动内容 风险
1 6 个 Agent 的 AGENTS.md 加"工具链协作"段(内容统一) L1 低(纯追加)
2 templates/toolchain/issue_assigned.md 精简 + 加仓库上下文 + Gitea API 引导 L2
3 templates/toolchain/review_request.md 精简 + 加 Gitea API 引导 L2
4 templates/toolchain/review_result.md 精简 L2
5 templates/toolchain/ci_failure.md 精简 + 加 CI 日志链接 L2
6 templates/toolchain/deploy_failure.md 精简 + 加排查步骤 L2
7 新建 templates/toolchain/mention.md @mention 通知模板 L2
8 src/api/toolchain_routes.py 提取 clone_url/html_url 传入模板;issue_comment 增加 @mention 解析;工具链 Mail 改为 request 类型 L2
9 不改 git-workflow 等 Skill 保持不变 L3
10 不改 daemon 核心逻辑、BootstrapBuilder、Skill 路由

六、验证方案

6.1 单元验证

验证点 方法
extract_mentions() 提取 @zhangfei-dev unit test
extract_mentions() 别名匹配 @张飞 → zhangfei-dev unit test
extract_mentions() 前缀匹配 @zhangfei → zhangfei-dev unit test
extract_mentions() 过滤自己 unit test
模板渲染新变量不报错 unit test

6.2 真实场景 E2E 验证

重复 Issue #32 的场景:

  1. 创建 Issue 指派张飞
  2. 验证:张飞收到的 Mail 含 clone URL + Gitea API 引导
  3. 验证:张飞 spawn 后知道该做什么(L1 AGENTS.md 有流程引导)
  4. 验证:张飞有疑问时去 Gitea Issue 评论(而不是 Control UI
  5. 在 Issue 评论 @赵云
  6. 验证:赵云收到 @mention Mail

七、不做的事(标记为后续)

标记 描述 原因
后续-1 Agent 离开工具链讨论后,是否有意识回到工具链 需要更多真实场景观察
后续-2 工具链使用标准在所有 Agent 间的一致性验证 L1 统一段落是第一步,需要 E2E 验证
后续-3 Mail 通道接入 BootstrapBuilder L2 注入 改动大,当前方案(L1 统一段落 + 模板引导)够用
后续-4 Skill 路由器自动触发(引擎注入) 改动 daemon 核心,当前靠 L1 文案触发

八、变更记录

日期 版本 变更
2026-06-09 v1.0 初版:E2E 真实场景暴露问题 → 四层改造方案 + @mention 通知 + Mail type 改造