feat: create_task加产线角色守卫(角色必须属当前产线角色集否则拒绝+返回可用角色清单); 新增list_roles共享工具(各产线自动继承); 工具描述去掉硬编码开发角色名——根治投标产线PM用requirement/design/develop建章节任务的死循环(2026-09-02)
This commit is contained in:
parent
77477c6caf
commit
0ef3dec4db
@ -29,15 +29,22 @@ from pipeline_core import (
|
||||
SDL_TOOLS = [
|
||||
ToolDefinition(
|
||||
name="create_task",
|
||||
description="创建开发任务,分配给角色agent执行",
|
||||
description="创建任务,分配给角色agent执行。角色必须属于当前产线(不同产线角色集不同),"
|
||||
"不确定有哪些角色时先调 list_roles 查看,禁止凭记忆用其他产线的角色名",
|
||||
parameters={
|
||||
"title": "任务标题",
|
||||
"role": "目标角色(requirement/design/develop/test/deploy)",
|
||||
"role": "目标角色(必须是当前产线的角色,用 list_roles 查看)",
|
||||
"description": "任务详细描述",
|
||||
"iteration_id": "归属迭代(可选,默认当前迭代)",
|
||||
},
|
||||
category="task",
|
||||
),
|
||||
ToolDefinition(
|
||||
name="list_roles",
|
||||
description="列出当前产线的全部角色(角色名/职责/别名)。建任务前用它确认当前产线有哪些可用角色",
|
||||
parameters={},
|
||||
category="task",
|
||||
),
|
||||
ToolDefinition(
|
||||
name="list_tasks",
|
||||
description="查看当前项目的任务列表",
|
||||
@ -326,6 +333,22 @@ SDL_ROLES = [
|
||||
|
||||
# ── handler 独立函数(签名统一 async def handler(sor, params, ctx) -> str) ──
|
||||
|
||||
async def _h_list_roles(sor, p, ctx):
|
||||
"""列出当前产线的全部角色(名称/职责/别名)。"""
|
||||
from pipeline_core import list_roles as _list_roles
|
||||
cur_pipeline = ctx.get("pipeline_id", "")
|
||||
if not cur_pipeline:
|
||||
return "无产线上下文(请先进入某产线的项目)"
|
||||
specs = _list_roles(cur_pipeline)
|
||||
if not specs:
|
||||
return "产线「%s」未注册角色集" % cur_pipeline
|
||||
lines = []
|
||||
for s in specs:
|
||||
aliases = "(别名: %s)" % "/".join(s.aliases) if getattr(s, "aliases", None) else ""
|
||||
lines.append("- %s:%s%s" % (s.name, s.description, aliases))
|
||||
return "当前产线「%s」共 %d 个角色:\n" % (cur_pipeline, len(specs)) + "\n".join(lines)
|
||||
|
||||
|
||||
async def _h_create_task(sor, p, ctx):
|
||||
pid = ctx.get("project_id", "")
|
||||
if not pid:
|
||||
@ -344,6 +367,21 @@ async def _h_create_task(sor, p, ctx):
|
||||
from .agent_loop import _normalize_role
|
||||
role = _normalize_role(role)
|
||||
|
||||
# 产线角色守卫:角色必须属于当前产线的角色集,否则拒绝创建。
|
||||
# 背景:共享 create_task 被多产线复用,PM 曾按工具描述里硬编码的开发角色名
|
||||
# (requirement/design/develop)在投标产线里建章节任务 → 角色无人认领、任务死循环。
|
||||
# 校验用 pipeline_core 注册表按当前产线查角色;能力包未注册时放行(逃逸阀,不阻塞)。
|
||||
from pipeline_core import get_role_spec, list_roles as _list_roles
|
||||
cur_pipeline = ctx.get("pipeline_id", "")
|
||||
if cur_pipeline and _list_roles(cur_pipeline):
|
||||
spec = get_role_spec(cur_pipeline, role)
|
||||
if not spec:
|
||||
avail = "、".join("%s(%s)" % (s.name, s.description) for s in _list_roles(cur_pipeline))
|
||||
return ("⚠️ 拒绝创建:角色「%s」不属于当前产线「%s」。当前产线可用角色:%s。"
|
||||
"请改用上述角色重新创建(可用 list_roles 随时查看)。"
|
||||
% (role, cur_pipeline, avail))
|
||||
role = spec.name # 归一到注册表规范名(比裸名拼接更可靠)
|
||||
|
||||
tid = getID()
|
||||
# 迭代归属:显式指定 > 当前迭代(该 project 最新创建的迭代)。
|
||||
# 「当前迭代」概念:新建迭代后当前迭代即新建的那个,任务默认归到它。
|
||||
@ -1784,6 +1822,7 @@ async def _h_verify_env(sor, p, ctx):
|
||||
|
||||
SDL_HANDLERS = {
|
||||
"create_task": _h_create_task,
|
||||
"list_roles": _h_list_roles,
|
||||
"list_tasks": _h_list_tasks,
|
||||
"task_detail": _h_task_detail,
|
||||
"reset_task_retry": _h_reset_task_retry,
|
||||
|
||||
@ -20,7 +20,7 @@ logger = logging.getLogger("pipeline.shared_ability")
|
||||
# sd_test_* / sd_deploy_envs 的 SDLC 专属工具都不在此列。
|
||||
_GENERIC_TOOL_NAMES = [
|
||||
# 任务
|
||||
"create_task", "list_tasks", "task_detail", "reset_task_retry",
|
||||
"create_task", "list_roles", "list_tasks", "task_detail", "reset_task_retry",
|
||||
"approve_task", "complete_task", "cancel_task",
|
||||
# agent 运行 / 诊断
|
||||
"start_agents", "diagnose_project", "check_progress",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user