[moz] fix(§21): GAP-1 issue_assigned 6路分流 + GAP-2 issue_closed auto-pass + GAP-3 Discussion Prompt v3

第一轮背靠背一致性检查发现的 3 个 GAP:

GAP-1: §21 §5 issue_assigned 按 type label 分流
- 从 labels 解析 business_type (feature/impl/bug/docs/refactor/test)
- 从 toolchain-templates.yaml get_steps() 获取对应 steps
- fallback 到硬编码 steps(向后兼容)

GAP-2: §21 §11 Issue closed 事件处理
- toolchain_handler verify 加 issue_closed auto-pass
- toolchain_routes 加 issue closed webhook → 纯通知 task

GAP-3: §21 §13.2 Discussion Prompt v3
- 新增 你是谁 段(agent_identity 注入)
- 新增 你必须做什么 4 维度(定位/建议/认领/风险)
- 新增 Comment 格式(角色名开头)
- Boids 行为准则不变
- 黑板 API 不变(§21 范围仅 toolchain)
This commit is contained in:
cfdaily
2026-06-20 23:14:43 +08:00
parent 6d1d906551
commit b0bca0df5c
3 changed files with 99 additions and 15 deletions
+61 -9
View File
@@ -1025,14 +1025,36 @@ async def _handle_issues(payload: Dict[str, Any]) -> None:
},
)
else:
title = f"Issue 指派: {issue_title} ({repo}#{issue_number})"
_send_toolchain_task(
to_agent=assignee,
title=title,
description=text,
event_type="issue_assigned",
action_type="issue_assigned",
steps=[
# §21 §5 按 type/* label 解析 business_type
business_type = "feature" # default
for lbl in labels_list:
lbl_lower = lbl.lower()
if "bug" in lbl_lower:
business_type = "bug"
elif "impl" in lbl_lower or "feature" in lbl_lower:
business_type = "feature" if "feature" in lbl_lower else "impl"
elif "docs" in lbl_lower or "documentation" in lbl_lower:
business_type = "docs"
elif "refactor" in lbl_lower:
business_type = "refactor"
elif "test" in lbl_lower:
business_type = "test"
# §21 §4 从 YAML 模板获取 stepsfallback 到硬编码)
from src.daemon.toolchain_templates import get_steps
yaml_steps = get_steps("issue_assigned", business_type)
if yaml_steps:
# 渲染占位符
rendered_steps = []
for s in yaml_steps:
s = s.replace("{issue_number}", str(issue_number))
s = s.replace("{brief}", brief)
s = s.replace("{title}", issue_title[:30])
rendered_steps.append(s)
steps_to_use = rendered_steps
else:
# fallback: 硬编码 steps(向后兼容)
steps_to_use = [
f"在开发目录执行 git 操作:\n a. git checkout main && git pull origin main\n b. git checkout -b fix/{issue_number}-{brief}",
"编码 + 写 UT",
"文档同步:如果本次改动涉及设计变更或接口变更,在同一分支更新 docs/design/ 对应文档。如无需更新,在 action report 中说明「文档无需更新」",
@@ -1040,7 +1062,16 @@ async def _handle_issues(payload: Dict[str, Any]) -> None:
f"CI 通过后创建 PRGitea API: POST /repos/{repo}/pullshead: fix/{issue_number}-{brief}, base: main)— PR body 必须含 Closes #{issue_number}",
"等 Review",
"提交 action reportPOST http://localhost:8083/api/projects/_toolchain/tasks/<task_id>/commentscomment_type=action_report)— 报告中必须说明文档是否需要更新及处理结果",
],
]
title = f"Issue 指派: {issue_title} ({repo}#{issue_number})"
_send_toolchain_task(
to_agent=assignee,
title=title,
description=text,
event_type="issue_assigned",
action_type="issue_assigned",
steps=steps_to_use,
context_data={
"issue_number": issue_number,
"repo": repo,
@@ -1048,9 +1079,30 @@ async def _handle_issues(payload: Dict[str, Any]) -> None:
"labels": labels,
"issue_body": issue_body or "(无描述)",
"brief": brief,
"business_type": business_type,
},
)
elif action == "closed":
# §21 §11 Issue closed 纯通知(auto-pass
assignee_login = ""
issue_assignees = issue.get("assignees") or []
if issue_assignees:
assignee_login = issue_assignees[-1].get("login", "")
if not assignee_login or assignee_login not in AGENT_IDS:
logger.debug("Issue closed but no valid assignee, skipping")
return
title = f"Issue 已关闭: {issue_title} ({repo}#{issue_number})"
_send_toolchain_task(
to_agent=assignee_login,
title=title,
description=f"## Issue 已关闭\n\n**{repo}#{issue_number}**: {issue_title}\n\nIssue 已被关闭。",
event_type="issue_closed",
action_type="issue_closed",
steps=[], # 纯通知,无步骤
context_data={"repo": repo, "issue_number": issue_number},
)
elif action == "opened":
if "部署失败" in issue_title:
# 从 Issue body 提取 commit hashGitea deploy workflow 格式)