feat: Step 5 引擎接入 + H1-H3/S3 修复 + 审计 D1/D2/D5 修复
CI / lint (pull_request) Failing after 7s
CI / test (pull_request) Has been skipped
CI / notify-on-failure (pull_request) Successful in 3s

引擎接入(dispatcher/spawner/ticker → handler 统一路由):
- dispatcher: guardrail/on_checks_passed/on_complete → handler 查询
- spawner: _build_prompt/_build_api_section → handler.build_prompt
- ticker: 虚拟项目扫描/assignee/claimed/review/幻觉门控 → handler 判断

Handler 缺陷修复:
- H1: _mark_task_status 加 3 次重试(防 DB 锁)
- H2: review @mention 加 comment_type='review'
- H3: review 非 approved 保持 review 状态(不标 working)
- S3: 通知链接改 Gitea(PR/Issue/Commit)

审计修复:
- D1: pre_spawn 返回值未检查 → 加 if not 抛 RuntimeError
- D2: PromptContext 缺 from_agent/mail_type → 从 must_haves 解析
- D5: _check_reply 查错表 → 恢复查 tasks 表找 in_reply_to

旧方法保留未删(deprecated),确认稳定后再清理。
This commit is contained in:
cfdaily
2026-06-10 22:33:03 +08:00
parent 2c970557c8
commit 8d72a1fa19
9 changed files with 648 additions and 173 deletions
+32 -6
View File
@@ -278,10 +278,30 @@ class AgentSpawner:
task_id, title, description, must_haves,
project_id, agent_id)
# mail 任务用精简模板
if project_id == "_mail":
return self._build_mail_prompt(
task_id, title, description, must_haves, agent_id)
# handler 路径:Task/Mail/Toolchain 用各自的 PromptSection 构建
from src.daemon.task_type_registry import TaskTypeRegistry
handler = TaskTypeRegistry.get_by_project(project_id)
if handler:
from src.daemon.prompt_composer import PromptContext
# 从 must_haves 解析 mail 元数据(from / performative
from_agent = ""
mail_type = ""
try:
meta = json.loads(must_haves) if must_haves else {}
from_agent = meta.get("from", "")
mail_type = meta.get("performative", meta.get("type", ""))
except Exception:
pass
ctx = PromptContext(
task_id=task_id, title=title, description=description or "",
must_haves=must_haves or "", project_id=project_id,
agent_id=agent_id, role=spawn_type,
spawn_type=spawn_type,
from_agent=from_agent, mail_type=mail_type,
)
return handler.build_prompt(ctx)
# 旧路径保留:_general 等非 handler 项目
# 走 BootstrapBuilder 新路径
if self.bootstrap_builder and task is not None:
@@ -321,8 +341,14 @@ class AgentSpawner:
def _build_api_section(self, project_id: str, task_id: str,
agent_id: str) -> str:
"""构建 API 回写操作指令(BootstrapBuilder 模式下补充)"""
# mail 任务直接 done,不走 review
success_status = '"done"' if project_id == "_mail" else '"review"'
# handler 项目(_mail/_toolchain)的 success_status 由 PromptSection 处理
# 这里只处理无 handler 的项目(normal task
from src.daemon.task_type_registry import TaskTypeRegistry
handler = TaskTypeRegistry.get_by_project(project_id)
if handler:
success_status = '"done"' if handler.target_success_status == "done" else '"review"'
else:
success_status = '"review"'
return f"""## 操作指令
### 状态回写