fix(task-chain): PM审核断链三处修复——未识别输出不再默认completed、review_complete仅终结角色可用、迭代边界只认显式completed/cancelled
根因:需求任务验收通过后设计任务未自动创建,项目卡在「无任务运行」的假终态。 1. pm_review_run 的 else 分支把未识别 PM 输出(deliver/纯文本/格式错误)静默当作 review_complete, 任务置 completed 且不创建下一角色任务,任务链断裂。改为追加纠错提示继续下一轮,轮次耗尽兜底 rejected。 2. 新增防御:非终结角色(requirement/design/develop/deploy_test/test)收到 review_complete 时修正为 approved。 3. 迭代边界检查从「非最新迭代即终止」改为「仅迭代状态 completed/cancelled 才终止」, 新建二期迭代不再阻断一期仍在跑的链。 4. PM prompt 澄清 review_complete 仅 deploy_prod 最后阶段使用。
This commit is contained in:
parent
41232c8295
commit
eb910bc7b8
@ -502,6 +502,7 @@ PM_SYSTEM_PROMPT = """你是项目经理(PM)。你的职责是项目计划
|
||||
## 任务链不能断(关键规则)
|
||||
- 审核通过里程碑任务(requirement / design,产出含多个应用/模块,或评审意见指明后续要落地开发)后,必须先规划并用 create_tasks 创建后续开发任务,再 review_approve。
|
||||
- 系统在 approve 后会自动补一个线性链的下一角色任务作为兜底;里程碑的并发拆分由你显式创建,不要等、不要断链。
|
||||
- **review_complete 只在「无下一阶段」时使用**——即最后一个角色 deploy_prod 验收通过后。requirement/design/develop/deploy_test/test 各阶段后面都还有下一角色,验收通过一律用 review_approve(系统自动创建下一角色任务),严禁用 review_complete 收尾,否则任务链断裂、下一阶段任务不会自动创建。
|
||||
|
||||
## 项目信息
|
||||
工作目录:__WORKSPACE__
|
||||
@ -537,7 +538,7 @@ __REPO_STATE__
|
||||
派发后续任务:{"action":"tool_call","tool":"create_tasks","params":{"tasks":[{"title":"契约定义","role":"design","key":"contract","description":"定义数据模型/API/目录规范"},{"title":"hr-system 开发","role":"develop","key":"hrsys","depends_on":["contract"],"description":"实现 hr-system 基础能力"},{"title":"hr-org 开发","role":"develop","key":"hrorg","depends_on":["contract"],"description":"实现 hr-org 基础能力"}]}}
|
||||
批准:{"action":"review_approve","comment":"审核意见","next_task_title":"下阶段标题","next_task_description":"描述"}
|
||||
驳回:{"action":"review_reject","comment":"原因","questions":"修改要求"}
|
||||
完成:{"action":"review_complete","comment":"总结"}
|
||||
完成:{"action":"review_complete","comment":"总结"}(仅 deploy_prod 最后阶段验收通过时使用)
|
||||
回退:{"action":"review_rollback","rollback_role":"develop","comment":"回退原因"}
|
||||
|
||||
审核标准:
|
||||
@ -1476,8 +1477,15 @@ async def pm_review_run(project_id, agent_id=None, model_name=None):
|
||||
msgs.append({"role": "assistant", "content": raw})
|
||||
msgs.append({"role": "user", "content": f"工具 {tool} 结果:\n{result}"})
|
||||
else:
|
||||
decision = {'status': 'completed', 'comment': raw[:200]}
|
||||
break
|
||||
# 未识别的 PM 输出(deliver/纯文本/格式错误)绝不能静默当作 review_complete——那会把任务
|
||||
# 置 completed 且不创建下一角色任务,任务链就此断掉(正是「需求验收通过但设计任务不自动创建」的根因)。
|
||||
# 正确做法:追加纠错提示继续下一轮,让 PM 重新给出正确决策;轮次耗尽由下方「审核超时」兜底为 rejected。
|
||||
logger.warning(f"pm_review_run 未识别 PM 输出 action={act.get('action', '?')}, turn={turn}: {raw[:200]}")
|
||||
msgs.append({"role": "assistant", "content": raw})
|
||||
msgs.append({"role": "user", "content":
|
||||
"你的输出无法解析。请严格按格式输出单个 JSON:"
|
||||
"review_approve / review_reject / review_complete / review_rollback 之一,不要输出其它内容。"})
|
||||
continue
|
||||
|
||||
if not decision:
|
||||
decision = {'status': 'rejected', 'comment': '审核超时'}
|
||||
@ -1485,6 +1493,16 @@ async def pm_review_run(project_id, agent_id=None, model_name=None):
|
||||
status = decision['status']
|
||||
comment = decision.get('comment', '')
|
||||
|
||||
# 防御:非终结角色被 review_complete 收尾 → 修正为 approved(避免断链)。
|
||||
# 只有无下一角色(deploy_prod)的 review_complete 才是合法终结。否则 requirement/design/develop/
|
||||
# deploy_test/test 被误收尾,下一阶段任务不会自动创建,项目卡在「无任务运行」却非「已结束」的假终态。
|
||||
if status == 'completed':
|
||||
_nr = await _get_next_role(task_role, project_id)
|
||||
if _nr:
|
||||
logger.warning(f"pm_review_run 非终结角色 {task_role} 收到 review_complete,修正为 approved 继续任务链 → {_nr}")
|
||||
status = 'approved'
|
||||
decision['status'] = 'approved'
|
||||
|
||||
if status == 'approved':
|
||||
from appPublic.uniqueID import getID
|
||||
pm_did = getID()
|
||||
@ -1509,16 +1527,17 @@ async def pm_review_run(project_id, agent_id=None, model_name=None):
|
||||
await approve_task(task_id, project_id, who="agent.pm", agent_id=agent_id, comment=comment)
|
||||
next_role = await _get_next_role(task_role, project_id)
|
||||
if next_role:
|
||||
# 迭代边界:任务若归属老迭代(非当前迭代=该项目最新创建的迭代),
|
||||
# 链到此终止,不再自动触发下一角色任务——「新迭代创建后老迭代不再产生新任务」。
|
||||
# 迭代边界:仅当任务归属的迭代已显式结束(completed/cancelled)才终止链。
|
||||
# 若该迭代仍 planning/in_progress/active,链继续在该迭代内创建下一角色任务——
|
||||
# 新建其它迭代(如二期)不应阻断一期仍在跑的链(否则「需求验收通过但设计任务不自动创建」)。
|
||||
task_iter = _task_iteration_name(task)
|
||||
if task_iter:
|
||||
cur = await sor.sqlExe(
|
||||
"SELECT iteration_name FROM sd_iterations WHERE project_id=${pid}$ ORDER BY created_at DESC LIMIT 1",
|
||||
{"pid": project_id})
|
||||
cur_name = getattr(cur[0], 'iteration_name', '') if cur else ''
|
||||
if cur_name and task_iter != cur_name:
|
||||
logger.info(f"迭代边界:任务 {task_id} 归属老迭代「{task_iter}」(当前「{cur_name}」),链终止")
|
||||
_it = await sor.sqlExe(
|
||||
"SELECT status FROM sd_iterations WHERE project_id=${pid}$ AND iteration_name=${name}$",
|
||||
{"pid": project_id, "name": task_iter})
|
||||
_it_status = getattr(_it[0], 'status', '') if _it else ''
|
||||
if _it_status in ('completed', 'cancelled'):
|
||||
logger.info(f"迭代边界:任务 {task_id} 归属迭代「{task_iter}」已 {_it_status},链终止")
|
||||
return {"status": "completed", "task_id": task_id, "comment": comment or "迭代已结束,链终止"}
|
||||
next_tid, next_title = await _create_next_task(sor, project_id, task, next_role, comment)
|
||||
return {"status": "approved", "task_id": task_id, "next_task_id": next_tid, "next_role": next_role, "comment": comment}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user