feat(sdlc): approve_task/complete_task 对齐 PM 行为推进任务链
- approve_task: 解决 pending review_reject + git 提交 + _get_next_role→迭代边界→_create_next_task 推进链 - complete_task: 同步交付件 review_status 标记 approved,避免任务 completed 但交付件仍 pending 不一致 - 会话 agent 手动 approve 不再断链(下一角色任务照常自动创建)
This commit is contained in:
parent
3c34eedb04
commit
8eedff7af9
@ -550,7 +550,12 @@ async def _h_reset_task_retry(sor, p, ctx):
|
||||
|
||||
|
||||
async def _h_approve_task(sor, p, ctx):
|
||||
"""审核通过任务(PM 验收):review → approved。"""
|
||||
"""审核通过任务(PM 验收):review → approved + 对齐 PM 行为推进任务链。
|
||||
|
||||
对齐 pm_review_run 的 approved 分支:解决该任务 pending 的 review_reject 问题、
|
||||
git 提交产出、查下一角色并创建下一阶段任务(含迭代边界检查)。这样会话 agent
|
||||
手动 approve 不会让任务链断(下一角色任务照常自动创建)。
|
||||
"""
|
||||
task_id = (p.get("task_id") or "").strip()
|
||||
if not task_id:
|
||||
return "需要任务ID"
|
||||
@ -560,15 +565,61 @@ async def _h_approve_task(sor, p, ctx):
|
||||
full = await _resolve_task_id(sor, task_id, pid)
|
||||
if not full:
|
||||
return f"任务不存在: {task_id}"
|
||||
recs = await sor.R('pipeline_tasks', {'id': full})
|
||||
if not recs:
|
||||
return f"任务不存在: {task_id}"
|
||||
task = recs[0]
|
||||
task_role = getattr(task, 'role', '') or ''
|
||||
title = getattr(task, 'title', '') or ''
|
||||
comment = (p.get("comment") or "").strip()
|
||||
|
||||
from .task_capability import approve_task
|
||||
ok, msg = await approve_task(full, pid, who="agent.pm",
|
||||
agent_id=ctx.get("user_id", ""),
|
||||
comment=(p.get("comment") or "").strip())
|
||||
return f"OK: {msg}" if ok else f"ERROR: {msg}"
|
||||
agent_id=ctx.get("user_id", ""), comment=comment)
|
||||
if not ok:
|
||||
return f"ERROR: {msg}"
|
||||
|
||||
# 解决该任务 pending 的 review_reject 问题(对齐 PM,防永久堆积)
|
||||
await sor.sqlExe(
|
||||
"UPDATE pipeline_agent_questions SET status='answered', answer=${a}$, "
|
||||
"answer_source='role_agent', answered_by=${role}$ "
|
||||
"WHERE task_id=${tid}$ AND status='pending' "
|
||||
"AND (problem_type='review_reject' "
|
||||
" OR ((problem_type IS NULL OR problem_type='') AND from_role IN ('pm','cockpit')))",
|
||||
{"a": "角色已响应,审核通过", "role": task_role or "role_agent", "tid": full})
|
||||
|
||||
# git 提交产出(对齐 PM:审核通过后统一提交;workspace_dir 空或 git 失败不阻断 approve)
|
||||
workspace_dir = ctx.get("workspace_dir", "") or ""
|
||||
if workspace_dir:
|
||||
try:
|
||||
from .agent_loop import _commit_repos_after_approve
|
||||
await _commit_repos_after_approve(workspace_dir, title)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# 推进任务链(对齐 PM):查下一角色 + 迭代边界 + 创建下一阶段任务
|
||||
from .agent_loop import _get_next_role, _create_next_task, _task_iteration_name
|
||||
next_role = await _get_next_role(task_role, pid)
|
||||
if next_role:
|
||||
task_iter = _task_iteration_name(task)
|
||||
if task_iter:
|
||||
_it = await sor.sqlExe(
|
||||
"SELECT status FROM sd_iterations WHERE project_id=${pid}$ AND iteration_name=${name}$",
|
||||
{"pid": pid, "name": task_iter})
|
||||
_it_status = getattr(_it[0], 'status', '') if _it else ''
|
||||
if _it_status in ('completed', 'cancelled'):
|
||||
return f"OK: {msg}(任务归属迭代「{task_iter}」已 {_it_status},链终止)"
|
||||
next_tid, next_title = await _create_next_task(sor, pid, task, next_role, comment)
|
||||
return f"OK: {msg};已创建下一阶段任务「{next_title}」({next_role},id={next_tid})"
|
||||
return f"OK: {msg}(无下一角色,任务链终结)"
|
||||
|
||||
|
||||
async def _h_complete_task(sor, p, ctx):
|
||||
"""标记任务完成(PM):approved/review → completed。"""
|
||||
"""标记任务完成(PM):approved/review → completed + 同步交付件标记 approved(对齐 PM)。
|
||||
|
||||
对齐 pm_review_run 的 review_complete 分支:先把交付件 review_status 从 pending 改 approved,
|
||||
避免任务 state=completed 但交付件 review_status 仍 pending 的状态不一致。
|
||||
"""
|
||||
task_id = (p.get("task_id") or "").strip()
|
||||
if not task_id:
|
||||
return "需要任务ID"
|
||||
@ -578,6 +629,10 @@ async def _h_complete_task(sor, p, ctx):
|
||||
full = await _resolve_task_id(sor, task_id, pid)
|
||||
if not full:
|
||||
return f"任务不存在: {task_id}"
|
||||
await sor.sqlExe(
|
||||
"UPDATE pipeline_deliverables SET review_status='approved', review_comment=${cm}$ "
|
||||
"WHERE task_id=${tid}$ AND review_status='pending'",
|
||||
{"cm": (p.get("comment") or "").strip(), "tid": full})
|
||||
from .task_capability import complete_task
|
||||
ok, msg = await complete_task(full, pid, who="agent.pm",
|
||||
agent_id=ctx.get("user_id", ""))
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user