Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ac4e28a57c | |||
| 41d60cca2c | |||
| bae3244e24 | |||
| e238eaec31 | |||
| b0bca0df5c | |||
| 6d1d906551 | |||
| 37b8115485 | |||
| 7c11c6b9aa |
@@ -0,0 +1,27 @@
|
||||
name: 文档任务
|
||||
about: 编写或更新文档
|
||||
title: "[moz] docs: "
|
||||
labels:
|
||||
- type/docs
|
||||
body:
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: 文档目标
|
||||
description: 要写什么文档,解决什么问题
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: path
|
||||
attributes:
|
||||
label: 文档路径
|
||||
description: 目标文件路径(如 docs/design/xxx.md)
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: outline
|
||||
attributes:
|
||||
label: 大纲
|
||||
description: 文档结构和要点
|
||||
validations:
|
||||
required: true
|
||||
@@ -0,0 +1,33 @@
|
||||
name: 实现任务
|
||||
about: 按设计文档实现功能
|
||||
title: "[moz] impl: "
|
||||
labels:
|
||||
- type/feat
|
||||
body:
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: 实现目标
|
||||
description: 清晰描述要实现什么
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: design_doc
|
||||
attributes:
|
||||
label: 设计文档
|
||||
description: 关联的设计文档路径(如 docs/design/xxx.md)
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: scope
|
||||
attributes:
|
||||
label: 实现范围
|
||||
description: 涉及哪些文件/模块
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: acceptance
|
||||
attributes:
|
||||
label: 验收标准
|
||||
validations:
|
||||
required: true
|
||||
@@ -0,0 +1,27 @@
|
||||
name: 重构任务
|
||||
about: 重构现有代码
|
||||
title: "[moz] refactor: "
|
||||
labels:
|
||||
- type/refactor
|
||||
body:
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: 重构目标
|
||||
description: 为什么重构,期望改善什么
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: scope
|
||||
attributes:
|
||||
label: 影响范围
|
||||
description: 涉及哪些文件/模块,是否有 breaking change
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: tests
|
||||
attributes:
|
||||
label: 测试保障
|
||||
description: 重构前哪些测试必须通过
|
||||
validations:
|
||||
required: true
|
||||
@@ -0,0 +1,171 @@
|
||||
# toolchain-templates.yaml
|
||||
# §21 §4 steps 模板化 — 按 action_type + business_type 查找
|
||||
# 占位符 {issue_number}/{brief}/{title}/{pr_number} 等运行时渲染
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# issue_assigned(按 Issue label 分 6 路 + infrastructure)
|
||||
# ---------------------------------------------------------------------------
|
||||
issue_assigned:
|
||||
feat:
|
||||
steps:
|
||||
- "理解需求(Issue body)→ 如有不明确在 Issue comment 追问"
|
||||
- "git checkout main && git pull origin main"
|
||||
- "git checkout -b feat/{issue_number}-{brief}"
|
||||
- "编码实现 + 写 UT"
|
||||
- "文档同步:如果本次改动涉及设计变更或接口变更,在同一分支更新 docs/design/ 对应文档。如无需更新,在 action report 中说明「文档无需更新」"
|
||||
- "git add -A && git commit -m '[moz] feat: {title}' && git push origin feat/{issue_number}-{brief}"
|
||||
- "CI 通过后创建 PR(body 含 Closes #{issue_number})"
|
||||
- "等 Review"
|
||||
output_template: |
|
||||
[Action Report]
|
||||
**分支**:feat/{issue_number}-{brief}
|
||||
**PR**:#{pr_number}
|
||||
**改动文件**:{files}
|
||||
**CI**:{ci_status}
|
||||
**文档同步**:{doc_status}
|
||||
|
||||
impl:
|
||||
steps:
|
||||
- "读设计文档(Issue body 中的路径)→ 理解实现范围"
|
||||
- "git checkout main && git pull origin main"
|
||||
- "git checkout -b impl/{issue_number}-{brief}"
|
||||
- "按设计编码实现 + 写 UT"
|
||||
- "文档同步:如果本次改动涉及设计变更或接口变更,在同一分支更新 docs/design/ 对应文档。如无需更新,在 action report 中说明「文档无需更新」"
|
||||
- "git add -A && git commit -m '[moz] impl: {title}' && git push origin impl/{issue_number}-{brief}"
|
||||
- "CI 通过后创建 PR(body 含 Closes #{issue_number} + 设计文档路径)"
|
||||
- "等 Review"
|
||||
output_template: |
|
||||
[Action Report]
|
||||
**设计文档**:{design_doc}
|
||||
**分支**:impl/{issue_number}-{brief}
|
||||
**PR**:#{pr_number}
|
||||
**改动文件**:{files}
|
||||
**CI**:{ci_status}
|
||||
**文档同步**:{doc_status}
|
||||
|
||||
bug:
|
||||
steps:
|
||||
- "读 Bug 描述 + 复现步骤(Issue body)"
|
||||
- "定位根因(读代码/日志,不要猜测)"
|
||||
- "git checkout main && git pull origin main"
|
||||
- "git checkout -b fix/{issue_number}-{brief}"
|
||||
- "修复 + 写回归测试"
|
||||
- "文档同步:如修复涉及设计/接口变更,同步更新 docs/design/ 对应文档"
|
||||
- "git add -A && git commit -m '[moz] fix: {title}' && git push origin fix/{issue_number}-{brief}"
|
||||
- "CI 通过后创建 PR(body 含 Closes #{issue_number} + 根因和修复方式)"
|
||||
- "等 Review"
|
||||
output_template: |
|
||||
[Action Report]
|
||||
**根因**:{root_cause}
|
||||
**修复方式**:{fix_approach}
|
||||
**分支**:fix/{issue_number}-{brief}
|
||||
**PR**:#{pr_number}
|
||||
**CI**:{ci_status}
|
||||
**文档同步**:{doc_status}
|
||||
|
||||
docs:
|
||||
steps:
|
||||
- "读文档目标(Issue body)"
|
||||
- "git checkout main && git pull origin main"
|
||||
- "git checkout -b docs/{issue_number}-{brief}"
|
||||
- "编写文档到 docs/ 对应目录"
|
||||
- "git add -A && git commit -m '[moz] docs: {title}' && git push origin docs/{issue_number}-{brief}"
|
||||
- "创建 PR(body 含 Closes #{issue_number})"
|
||||
- "等 Review"
|
||||
output_template: |
|
||||
[Action Report]
|
||||
**文档路径**:{doc_path}
|
||||
**分支**:docs/{issue_number}-{brief}
|
||||
**PR**:#{pr_number}
|
||||
|
||||
refactor:
|
||||
steps:
|
||||
- "读重构目标 + 影响范围(Issue body)"
|
||||
- "git checkout main && git pull origin main"
|
||||
- "git checkout -b refactor/{issue_number}-{brief}"
|
||||
- "重构 + 确保现有测试不 break(python3 -m pytest tests/unit/ -q)"
|
||||
- "文档同步:如重构涉及架构变更,同步更新 docs/design/ 对应文档"
|
||||
- "git add -A && git commit -m '[moz] refactor: {title}' && git push origin refactor/{issue_number}-{brief}"
|
||||
- "CI 通过后创建 PR(body 含 Closes #{issue_number} + 重构内容和影响范围)"
|
||||
- "等 Review"
|
||||
output_template: |
|
||||
[Action Report]
|
||||
**重构范围**:{scope}
|
||||
**测试结果**:{test_result} passed
|
||||
**分支**:refactor/{issue_number}-{brief}
|
||||
**PR**:#{pr_number}
|
||||
**CI**:{ci_status}
|
||||
**文档同步**:{doc_status}
|
||||
|
||||
test:
|
||||
steps:
|
||||
- "读测试目标(Issue body)"
|
||||
- "git checkout main && git pull origin main"
|
||||
- "git checkout -b test/{issue_number}-{brief}"
|
||||
- "编写测试脚本到 tests/ 对应目录"
|
||||
- "运行测试验证(python3 -m pytest {test_file} -v)"
|
||||
- "git add -A && git commit -m '[moz] test: {title}' && git push origin test/{issue_number}-{brief}"
|
||||
- "创建 PR(body 含 Closes #{issue_number})"
|
||||
- "等 Review"
|
||||
output_template: |
|
||||
[Action Report]
|
||||
**测试文件**:{test_file}
|
||||
**测试结果**:{test_result}
|
||||
**分支**:test/{issue_number}-{brief}
|
||||
**PR**:#{pr_number}
|
||||
|
||||
infrastructure:
|
||||
steps:
|
||||
- "根据 Issue body 中的错误来源和日志片段排查问题"
|
||||
- "修复基础设施问题(CI runner/网络/Gitea/磁盘等)"
|
||||
- "修复后在 Issue 上 comment 说明修复方式和结果"
|
||||
- "提交 action report(POST http://localhost:8083/api/projects/_toolchain/tasks/<task_id>/comments,comment_type=action_report)"
|
||||
output_template: |
|
||||
[Action Report]
|
||||
**问题**:{problem}
|
||||
**根因**:{root_cause}
|
||||
**修复方式**:{fix}
|
||||
**验证**:{verification}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# ci_failure
|
||||
# ---------------------------------------------------------------------------
|
||||
ci_failure:
|
||||
steps:
|
||||
- "查看完整 CI 日志(PR 页面或 Gitea Actions 页面)"
|
||||
- "根据 CI 日志判断失败原因类型:\n a. 代码问题(lint/test 失败)→ 修复失败的测试 → push 到原分支 → CI 自动重跑\n b. 基础设施问题(runner 环境/Python/venv/Gitea/网络故障)→ 在该仓库创建 Issue 指派 jiangwei-infra(label 必须包含 type/infrastructure)"
|
||||
- "文档同步:如修复涉及设计/接口变更,同步更新 docs/design/ 对应文档"
|
||||
- "提交 action report(POST http://localhost:8083/api/projects/_toolchain/tasks/<task_id>/comments,comment_type=action_report)— 报告中说明判断的原因类型和执行的操作,以及文档是否需要更新"
|
||||
output_template: |
|
||||
[Action Report]
|
||||
**原因类型**:{cause_type}
|
||||
**操作**:{action}
|
||||
**CI 重跑**:{ci_status}
|
||||
**文档同步**:{doc_status}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# review_result — APPROVED
|
||||
# ---------------------------------------------------------------------------
|
||||
review_result_approved:
|
||||
steps:
|
||||
- "合并 PR(Gitea API: POST /repos/{repo}/pulls/{pr_number}/merge)"
|
||||
- "提交 action report(POST http://localhost:8083/api/projects/_toolchain/tasks/<task_id>/comments,comment_type=action_report)"
|
||||
output_template: |
|
||||
[Action Report]
|
||||
**PR #{pr_number}**:merged
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# review_result — REQUEST_CHANGES
|
||||
# ---------------------------------------------------------------------------
|
||||
review_result_request_changes:
|
||||
steps:
|
||||
- "按审查意见逐条修改代码"
|
||||
- "文档同步:如审查涉及设计/接口变更,同步更新 docs/design/ 对应文档"
|
||||
- "push 到原分支 → CI 自动跑"
|
||||
- "CI 通过后等重新 Review"
|
||||
- "提交 action report(POST http://localhost:8083/api/projects/_toolchain/tasks/<task_id>/comments,comment_type=action_report)— 报告中必须说明文档是否需要更新及处理结果"
|
||||
output_template: |
|
||||
[Action Report]
|
||||
**修改内容**:{changes}
|
||||
**CI**:{ci_status}
|
||||
**文档同步**:{doc_status}
|
||||
@@ -2,7 +2,7 @@
|
||||
title: "Issue-Centric Orchestration — Gitea Issue 替代黑板 DB 协作面"
|
||||
created: 2026-06-19
|
||||
version: v2.1 draft
|
||||
status: draft
|
||||
status: superseded by §21 (toolchain 部分)
|
||||
changelog: v2.1 修正 M1(dispatcher 直接 SQL 声明)+ M2(Phase 格式)+ S1/S2(TaskAdapter 残留清理)
|
||||
v2.0 纳入姜维+司马懿 Review 反馈 + 庞统 Repository 模式修正
|
||||
v1.1 纳入姜维 Review 反馈
|
||||
|
||||
@@ -1025,14 +1025,38 @@ 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 = "feat" # default
|
||||
for lbl in labels_list:
|
||||
lbl_lower = lbl.lower()
|
||||
if "bug" in lbl_lower:
|
||||
business_type = "bug"
|
||||
elif "impl" in lbl_lower:
|
||||
business_type = "impl"
|
||||
elif "feat" in lbl_lower:
|
||||
business_type = "feat"
|
||||
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 模板获取 steps(fallback 到硬编码)
|
||||
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 +1064,16 @@ async def _handle_issues(payload: Dict[str, Any]) -> None:
|
||||
f"CI 通过后创建 PR(Gitea API: POST /repos/{repo}/pulls,head: fix/{issue_number}-{brief}, base: main)— PR body 必须含 Closes #{issue_number}",
|
||||
"等 Review",
|
||||
"提交 action report(POST http://localhost:8083/api/projects/_toolchain/tasks/<task_id>/comments,comment_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 +1081,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 hash(Gitea deploy workflow 格式)
|
||||
|
||||
+32
-6
@@ -103,9 +103,9 @@ SPAWN_PROMPT_TEMPLATE = """{identity_section}
|
||||
"""
|
||||
|
||||
|
||||
DISCUSSION_PROMPT_TEMPLATE = """你被 spawn 来参与黑板讨论。这是一个 v2.9 四相循环的讨论环节。
|
||||
DISCUSSION_PROMPT_TEMPLATE = """你被 spawn 来参与讨论。这是一个四相循环的讨论环节。
|
||||
|
||||
## 你的任务
|
||||
## 讨论主题
|
||||
|
||||
{goal_snapshot}
|
||||
|
||||
@@ -113,14 +113,38 @@ DISCUSSION_PROMPT_TEMPLATE = """你被 spawn 来参与黑板讨论。这是一
|
||||
|
||||
{constraints}
|
||||
|
||||
## 你是谁
|
||||
|
||||
{agent_identity}
|
||||
|
||||
## 你必须做什么
|
||||
|
||||
读完需求后,在黑板 comment 回应(必须,不是可选):
|
||||
|
||||
1.【定位】这个需求和你有什么关系?你的专业能力能贡献什么?
|
||||
2.【建议】你对实现方案有什么建议?(技术选型、数据来源、实现路径)
|
||||
3.【认领】如果你需要参与,创建 sub task 并在 parent task comment 注册:
|
||||
- 创建 sub task: POST http://{api_host}:{api_port}/api/projects/{project_id}/tasks
|
||||
body: {{"title": "...", "description": "...", "task_type": "...", "parent_task": "{task_id}", "must_haves": "{{\"capability\": \"...\"}}"}}
|
||||
- 创建后在 parent task comment: "[你的角色名] 我创建了 sub: 任务名,我负责 简述"
|
||||
4.【风险】如果你发现风险、不合理的假设、或遗漏的环节,直接提出
|
||||
|
||||
⚠️ 每个 agent 必须 comment。即使你认为和自己无关,也要说明原因——这证明你读过并思考过了。
|
||||
|
||||
## Comment 格式
|
||||
|
||||
你的 comment 必须以角色名开头,让其他人知道你是谁:
|
||||
[角色名] 你的观点
|
||||
例:[张飞] 我来负责策略编码,用 vnpy CtaTemplate 实现。
|
||||
例:[关羽] 这个策略需要风控,连亏 3 天应暂停。
|
||||
例:[赵云] 数据已就绪,2024-08 缺失已补齐。
|
||||
|
||||
## 黑板 API
|
||||
|
||||
你可以随时:
|
||||
- 读黑板:GET http://{api_host}:{api_port}/api/projects/{project_id}/tasks/{task_id}?expand=all(含 comments、outputs)
|
||||
- 读黑板:GET http://{api_host}:{api_port}/api/projects/{project_id}/tasks/{task_id}?expand=all
|
||||
- 写 comment:POST http://{api_host}:{api_port}/api/projects/{project_id}/tasks/{task_id}/comments
|
||||
body: {{"author": "{agent_id}", "body": "内容(@agent-id 自动路由)"}}
|
||||
body: {{"author": "{agent_id}", "body": "内容"}}
|
||||
- 创建 sub task:POST http://{api_host}:{api_port}/api/projects/{project_id}/tasks
|
||||
body: {{"title": "...", "description": "...", "task_type": "...", "parent_task": "{task_id}", "must_haves": "{{\"capability\": \"...\"}}"}}
|
||||
- 认领任务:POST http://{api_host}:{api_port}/api/projects/{project_id}/tasks/{{sub_task_id}}/claim
|
||||
|
||||
## 行为准则
|
||||
@@ -387,12 +411,14 @@ curl -X POST http://{self.api_host}:{self.api_port}/api/projects/{project_id}/ta
|
||||
goal_snapshot = description or title
|
||||
constraints = must_haves or "(无特殊约束)"
|
||||
|
||||
agent_identity = self._inject_agent_identity(agent_id)
|
||||
return DISCUSSION_PROMPT_TEMPLATE.format(
|
||||
goal_snapshot=goal_snapshot,
|
||||
constraints=constraints,
|
||||
project_id=project_id,
|
||||
task_id=task_id,
|
||||
agent_id=agent_id,
|
||||
agent_identity=agent_identity,
|
||||
api_host=self.api_host,
|
||||
api_port=self.api_port,
|
||||
)
|
||||
|
||||
@@ -264,7 +264,7 @@ class ToolchainConstraintsSection:
|
||||
'| “步骤太多了,选几个做就行” | ❌ 错!必须逐条执行,不可跳过 |',
|
||||
'| “这个步骤不适用于当前情况” | ❌ 如果确实不适用,在 action report 中说明原因,但其他步骤必须执行 |',
|
||||
'| “CI/部署失败不是我代码的问题,我什么也不用做” | ❌ 错!即使是基础设施问题,你也必须创建 Issue 指派 jiangwei-infra(body 含错误来源链接 + 日志 + 判断依据),并在 action report 中说明。不能只报告“不是我的问题”就完事 |',
|
||||
'| "文档以后再说" | ❌ 错!文档同步和代码改动在同一 PR 中完成,action report 中必须说明文档处理情况 |',
|
||||
'| “文档以后再说” | ❌ 错!文档同步和代码改动在同一 PR 中完成,action report 中必须说明文档处理情况 |',
|
||||
"",
|
||||
]
|
||||
return "\n".join(lines)
|
||||
@@ -331,6 +331,11 @@ class ToolchainHandler(BaseTaskHandler):
|
||||
return VerifyResult(True, "merged_passthrough",
|
||||
"review_merged auto-pass")
|
||||
|
||||
# 特殊处理:issue_closed 始终通过(纯通知, §21 §11)
|
||||
if meta.get("action_type") == "issue_closed":
|
||||
return VerifyResult(True, "issue_closed_passthrough",
|
||||
"issue_closed auto-pass")
|
||||
|
||||
# 1. 优先检查 action_report comment
|
||||
report_row = conn.execute(
|
||||
"SELECT id FROM comments WHERE task_id=? "
|
||||
|
||||
@@ -8,7 +8,7 @@ from __future__ import annotations
|
||||
import logging
|
||||
from collections import defaultdict
|
||||
from pathlib import Path
|
||||
from typing import Dict
|
||||
from typing import Dict, List, Optional
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -87,3 +87,65 @@ def render_template(name: str, variables: Dict[str, str]) -> str:
|
||||
def clear_cache() -> None:
|
||||
"""清空模板缓存(用于测试或热更新)"""
|
||||
_template_cache.clear()
|
||||
global _steps_cache
|
||||
_steps_cache = None # 重置为 None,强制下次 reload
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# §21 §4.2 YAML steps 模板加载
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
STEPS_YAML_PATH = Path(__file__).parent.parent.parent / "config" / "toolchain-templates.yaml"
|
||||
|
||||
_steps_cache: Optional[dict] = None
|
||||
|
||||
|
||||
def _load_steps_yaml() -> dict:
|
||||
"""加载并缓存 toolchain-templates.yaml。"""
|
||||
global _steps_cache
|
||||
if _steps_cache is not None:
|
||||
return _steps_cache
|
||||
try:
|
||||
import yaml
|
||||
with open(STEPS_YAML_PATH, encoding="utf-8") as f:
|
||||
_steps_cache = yaml.safe_load(f) or {}
|
||||
logger.debug("Loaded steps YAML: %d action_types", len(_steps_cache))
|
||||
except FileNotFoundError:
|
||||
logger.warning("Steps YAML not found: %s", STEPS_YAML_PATH)
|
||||
_steps_cache = {}
|
||||
except Exception as e:
|
||||
logger.error("Failed to load steps YAML: %s", e)
|
||||
_steps_cache = {}
|
||||
return _steps_cache
|
||||
|
||||
|
||||
def get_steps(action_type: str, business_type: str = "") -> List[str]:
|
||||
"""从 YAML 模板配置获取 steps。
|
||||
|
||||
Args:
|
||||
action_type: 动作类型(issue_assigned / ci_failure / ...)
|
||||
business_type: 业务子类型(feature/impl/bug/docs/refactor/test/infrastructure)
|
||||
|
||||
Returns:
|
||||
steps 列表,找不到返回空列表
|
||||
"""
|
||||
templates = _load_steps_yaml()
|
||||
section = templates.get(action_type, {})
|
||||
if isinstance(section, dict) and business_type:
|
||||
subsection = section.get(business_type, {})
|
||||
return subsection.get("steps", [])
|
||||
if isinstance(section, dict):
|
||||
return section.get("steps", [])
|
||||
return []
|
||||
|
||||
|
||||
def get_output_template(action_type: str, business_type: str = "") -> str:
|
||||
"""从 YAML 模板配置获取 output_template。"""
|
||||
templates = _load_steps_yaml()
|
||||
section = templates.get(action_type, {})
|
||||
if isinstance(section, dict) and business_type:
|
||||
subsection = section.get(business_type, {})
|
||||
return subsection.get("output_template", "")
|
||||
if isinstance(section, dict):
|
||||
return section.get("output_template", "")
|
||||
return ""
|
||||
|
||||
Reference in New Issue
Block a user