Compare commits

..

3 Commits

Author SHA1 Message Date
cfdaily 4aec10225f chore: retrigger CI after ensurepip fix
CI / lint (pull_request) Successful in 7s
CI / test (pull_request) Successful in 27s
CI / frontend (pull_request) Successful in 10s
CI / notify-on-failure (pull_request) Successful in 0s
2026-06-19 09:37:33 +08:00
cfdaily f2c864aa17 [moz] docs(§19): fix M1 JSON 配置块 delivery.mode 同步改为 announce
CI / lint (pull_request) Failing after 7s
CI / test (pull_request) Has been skipped
CI / frontend (pull_request) Has been skipped
CI / notify-on-failure (pull_request) Successful in 1s
司马懿 M1:3 处 JSON 配置块 delivery.mode 仍为 none,与设计要点文字不一致。
同步修正为 announce。
2026-06-19 07:55:51 +08:00
cfdaily 8f671a7065 [moz] docs(§19): cron delivery mode 修正 none→announce
CI / lint (pull_request) Failing after 6s
CI / test (pull_request) Has been skipped
CI / frontend (pull_request) Has been skipped
CI / notify-on-failure (pull_request) Successful in 2s
根因:isolated session + delivery:none 导致 cron 执行后零可见性
修复:L1/L2/IMPROVE cron delivery 统一改为 announce
2026-06-19 07:53:53 +08:00
5 changed files with 45 additions and 236 deletions
-1
View File
@@ -26,7 +26,6 @@ jobs:
- name: Setup Python
run: |
rm -rf /tmp/ci-venv-lint
python3 -m venv /tmp/ci-venv-lint
/tmp/ci-venv-lint/bin/pip install --quiet --upgrade pip
/tmp/ci-venv-lint/bin/pip install --quiet flake8
+13 -94
View File
@@ -391,11 +391,7 @@ def verify_completion(self, task_id: str, db_path: Path) -> VerifyResult:
#### 完整设计
三分路的详细设计见 §6.4(基础设施 Issue 转交流程)和 toolchain_handler.py 实现(`_handle_infrastructure_failure` / `_classify_failure`)。
#### 首次 steps 分支指引
三分路是 verify 失败后的兜底机制。此外,ci_failure 和 deploy_failure 的首次 toolchain task steps 中**已包含分支指引**——agent 在执行过程中自行判断失败原因,如果是基础设施问题则直接创建 Issue 指派 jiangwei-infra(见 §6.4)。三分路作为第二道防线,覆盖 agent 未正确判断或未执行分支的情况。
三分路的详细伪代码、失败上限、决策依据见 §5.2.1~§5.2.3on_failure 分路处理详细设计)。
### 5.3 action_report comment 格式
@@ -435,9 +431,9 @@ Agent 可能写了 action_report 但没真做。缓解机制:
| Review 请求 → reviewer | review_request | toolchain | 4 步 | 读 diff + 审查 + 提交 Review + report |
| Review 有新提交 → reviewer | review_updated | toolchain | 4 步 | 读 diff + 检查修改 + 提交 Review + report |
| Review 评论 → PR 作者 | review_comment | toolchain | 3 步 | 查看评论 + 响应(修改/回复)+ report |
| CI 失败 → PR 作者 | ci_failure | toolchain | 3 步 | 查 CI 日志 + 分支判断(代码问题自己修 / 基础设施问题提 Issue 给姜维)+ report |
| Issue 指派 → 开发者 | issue_assigned / infrastructure_failure | toolchain | 6 步(编码)或 4 步(运维) | 按 label 分流:type/infrastructure → 运维排查;其他 → 创建分支 + 编码 + push + CI + PR + report |
| 部署失败 → 运维 | deploy_failure | toolchain | 3 步 | 查日志 + 分支判断(代码/配置问题自己修 / 基础设施问题提 Issue 给姜维)+ report |
| CI 失败 → PR 作者 | ci_failure | toolchain | 4 步 | 查 CI 日志 + 修测试 + push + report |
| Issue 指派 → 开发者 | issue_assigned | toolchain | 6 步 | 创建分支 + 编码 + push + CI + PR + report |
| 部署失败 → 运维 | deploy_failure | toolchain | 4 步 | 查日志 + 排查 + 修+重部署 + report |
| @mention → 被@者 | mention | toolchain | 按 guidance | 按 mention 模板的 response_guidance + report |
| PR 合并 → PR 作者 | review_merged | toolchain | 0 步 | 纯通知,走 _send_toolchain_tasksteps 为空,verify 始终通过) |
@@ -506,42 +502,29 @@ event_type: ci_failure
action_type: ci_failure
steps:
1. 查看完整 CI 日志(PR 页面或 Gitea Actions 页面)
2. 根据 CI 日志判断失败原因类型:
a. 代码问题(lint/test 失败)→ 修复失败的测试 → push 到原分支 → CI 自动重跑
b. 基础设施问题(runner 环境/Python/venv/Gitea/网络故障)→ 在该仓库创建 Issue 指派 jiangwei-infra(见 §6.4),label 必须包含 type/infrastructure
3. 提交 action report — 报告中说明判断的原因类型和执行的操作
2. 修复失败的测试
3. push → CI 自动重跑
4. 提交 action report
context:
pr_number, repo, branch, error_summary
```
**分支设计说明**:原设计假设"CI 失败 = 代码问题"steps 只有"修测试 + push"一条路径。实际运行中发现 CI 失败可能是 runner 环境故障(如 ensurepip 失败),agent 判断为基础设施问题后不知道该做什么。现在 steps 中明确两条分支,agent 自行判断后走对应路径。
#### Issue 指派 → 开发者
```
event_type: issue_assigned 或 infrastructure_failure
action_type: issue_assigned 或 infrastructure_failure
steps(按 label 分流):
# 默认路径(编码任务):
event_type: issue_assigned
action_type: issue_assigned
steps:
1. 创建分支 fix/{issue_number}-{brief}
2. 编码 + 写 UT
3. push → 等 CI
4. CI 通过后创建 PRGitea API: POST /repos/{repo}/pulls
5. 等 Review
6. 提交 action report
# type/infrastructure label 路径(运维任务):
1. 根据 Issue body 中的错误来源和日志片段排查问题
2. 修复基础设施问题(如修复 CI runner 环境、恢复网络、重启服务等)
3. 修复后在 Issue 上 comment 说明修复方式和结果
4. 提交 action report
context:
issue_number, repo, issue_title, labels, issue_body, brief
```
**label 分流说明**issue_assigned handler 检查 label 中是否包含 `type/infrastructure`。如果是,走运维排查 stepsevent_type 设为 infrastructure_failureverify 始终 auto-pass 防递归);否则走编码 steps。
#### 部署失败 → 运维
```
@@ -549,10 +532,9 @@ event_type: deploy_failure
action_type: deploy_failure
steps:
1. 检查 deploy 日志
2. 根据 deploy 日志判断失败原因类型:
a. 代码/配置问题(rsync 路径错、依赖缺失、启动失败)→ 修复 → 重新部署
b. 基础设施问题(Gitea 不可用、网络不通、磁盘满、SSH 故障)→ 在该仓库创建 Issue 指派 jiangwei-infra(见 §6.4),label 必须包含 type/infrastructure
3. 提交 action report — 报告中说明判断的原因类型和执行的操作
2. 排查失败原因
3. 修复并重新部署
4. 提交 action report
context:
repo, commit_sha, reason
```
@@ -595,69 +577,6 @@ context:
**spawn 说明**review_merged 仍会触发 spawnAgent 只需阅读通知),verify auto-pass 后标 done。未来可优化为 ticker 直接 auto-done 跳过 spawn。
### 6.4 基础设施 Issue 转交流程
当 ci_failure / deploy_failure 的 agent 在调查后发现失败原因是基础设施问题(非代码问题),需要创建 Gitea Issue 指派 jiangwei-infra。
#### Issue 提在哪里
**根据问题来源决定**——哪个仓库的 CI/部署失败了,Issue 就提到那个仓库。CI runner 是全局共享的(一个 Mac mini),但 Issue 挂在触发的仓库最自然。如果 runner 故障影响多个仓库,各仓库会各自触发 ci_failure task,姜维看到任何一个 Issue 就能定位全局问题。
#### Issue 格式规范
```markdown
## 问题描述
<简要描述问题现象>
## 错误来源
- 仓库: <repo>
- PR/Commit: <链接>
- CI/Deploy run: <Gitea Actions 页面链接>
## 日志关键片段
```
<错误日志摘要,不需全文,但要让排查者看到关键信息>
```
## 判断依据
<为什么判断为基础设施问题而非代码问题>
```
**必填字段**:问题描述、错误来源(含链接)、日志片段、判断依据。Issue body 不完整会导致姜维无法高效排查。
**label 要求**:必须包含 `type/infrastructure`,用于 issue_assigned handler 分流(见下)。
#### issue_assigned handler label 分流
当 Gitea Issue 指派触发 webhook 时,issue_assigned handler 检查 label
| label 包含 type/infrastructure | event_type | steps |
|---|---|---|
| 是 | infrastructure_failure | 运维排查:根据 Issue body 排查问题 → 修复 → Issue comment 说明修复方式 → action report |
| 否 | issue_assigned | 编码:创建分支 → 编码 → push → CI → PR → 等 Review → action report |
基础设施路径的 verify 始终 auto-pass(防递归,已有逻辑覆盖)。
⚠️ **label 分流当前为设计目标**toolchain_handler.py 尚未实现 issue_assigned 的 label 检查。当前只有 `_handle_infrastructure_failure`verify 失败时)创建 infrastructure_failure task。issue_assigned handler 的 label 分流在后续代码 PR 中实现。
⚠️ **label 预创建**:使用前需确认仓库中已创建名为 `type/infrastructure` 的 label。sanguo_moziplus_v2 仓库已创建(ID=98)。其他仓库使用前需先创建。
#### API 指令位置
Issue 创建的 API 调用方式(curl 示例)统一在 ToolchainApiSection 中,与 action_report / comment 指引并列。steps 指令中不重复 API 调用方式,只描述"做什么"。
#### Red Flags 补充
硬约束 Red Flags 表新增一条:
| Agent 想法 | Red Flag 驳回 |
|---|---|
| "CI/部署失败不是我代码的问题,我什么也不用做" | ❌ 错!即使是基础设施问题,你也必须创建 Issue 指派 jiangwei-infrabody 含错误来源链接 + 日志 + 判断依据),并在 action report 中说明。不能只报告"不是我的问题"就完事 |
---
## §7. _send_toolchain_task 函数设计
+32 -57
View File
@@ -778,8 +778,9 @@ def _send_deploy_failure_task(repo: str, pr_number: int, pr_title: str, reason:
action_type="deploy_failure",
steps=[
"检查 deploy 日志",
"根据 deploy 日志判断失败原因类型:\n a. 代码/配置问题(rsync 路径错、依赖缺失、启动失败)→ 修复 → 重新部署\n b. 基础设施问题(Gitea 不可用、网络不通、磁盘满、SSH 故障)→ 在该仓库创建 Issue 指派 jiangwei-infra(见下方「需要创建 Issue 时」),label 必须包含 type/infrastructure",
"提交 action reportPOST http://localhost:8083/api/projects/_toolchain/tasks/<task_id>/commentscomment_type=action_report)— 报告中说明判断的原因类型和执行的操作",
"排查失败原因",
"修复并重新部署",
"提交 action reportPOST http://localhost:8083/api/projects/_toolchain/tasks/<task_id>/commentscomment_type=action_report",
],
context_data={
"repo": repo,
@@ -996,58 +997,30 @@ async def _handle_issues(payload: Dict[str, Any]) -> None:
"brief": brief,
})
# 检查是否是基础设施 Issue(按 label 分流)
is_infrastructure = any("infrastructure" in lbl.lower() for lbl in labels_list)
if is_infrastructure:
infra_steps = [
"根据 Issue body 中的错误来源和日志片段排查问题",
"修复基础设施问题(如修复 CI runner 环境、恢复网络、重启服务等)",
"修复后在 Issue 上 comment 说明修复方式和结果",
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=[
f"创建分支 fix/{issue_number}-{brief}",
"编码 + 写 UT",
"push → 等 CI",
f"CI 通过后创建 PRGitea API: POST /repos/{repo}/pulls",
"等 Review",
"提交 action reportPOST http://localhost:8083/api/projects/_toolchain/tasks/<task_id>/commentscomment_type=action_report",
]
title = f"基础设施 Issue: {issue_title} ({repo}#{issue_number})"
_send_toolchain_task(
to_agent=assignee,
title=title,
description=text,
event_type="infrastructure_failure",
action_type="infrastructure_failure",
steps=infra_steps,
context_data={
"issue_number": issue_number,
"repo": repo,
"issue_title": issue_title,
"labels": labels,
"issue_body": issue_body or "(无描述)",
"brief": brief,
},
)
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=[
f"创建分支 fix/{issue_number}-{brief}",
"编码 + 写 UT",
"push → 等 CI",
f"CI 通过后创建 PRGitea API: POST /repos/{repo}/pulls",
"等 Review",
"提交 action reportPOST http://localhost:8083/api/projects/_toolchain/tasks/<task_id>/commentscomment_type=action_report",
],
context_data={
"issue_number": issue_number,
"repo": repo,
"issue_title": issue_title,
"labels": labels,
"issue_body": issue_body or "(无描述)",
"brief": brief,
},
)
],
context_data={
"issue_number": issue_number,
"repo": repo,
"issue_title": issue_title,
"labels": labels,
"issue_body": issue_body or "(无描述)",
"brief": brief,
},
)
elif action == "opened":
if "部署失败" in issue_title:
@@ -1070,8 +1043,9 @@ async def _handle_issues(payload: Dict[str, Any]) -> None:
action_type="deploy_failure",
steps=[
"检查 deploy 日志",
"根据 deploy 日志判断失败原因类型:\n a. 代码/配置问题(rsync 路径错、依赖缺失、启动失败)→ 修复 → 重新部署\n b. 基础设施问题(Gitea 不可用、网络不通、磁盘满、SSH 故障)→ 在该仓库创建 Issue 指派 jiangwei-infra(见下方「需要创建 Issue 时」),label 必须包含 type/infrastructure",
"提交 action reportPOST http://localhost:8083/api/projects/_toolchain/tasks/<task_id>/commentscomment_type=action_report)— 报告中说明判断的原因类型和执行的操作",
"排查失败原因",
"修复并重新部署",
"提交 action reportPOST http://localhost:8083/api/projects/_toolchain/tasks/<task_id>/commentscomment_type=action_report",
],
context_data={
"repo": repo,
@@ -1152,8 +1126,9 @@ async def _handle_issue_comment(payload: Dict[str, Any]) -> None:
action_type="ci_failure",
steps=[
"查看完整 CI 日志(PR 页面或 Gitea Actions 页面)",
"根据 CI 日志判断失败原因类型:\n a. 代码问题(lint/test 失败)→ 修复失败的测试 → push 到原分支 → CI 自动重跑\n b. 基础设施问题(runner 环境/Python/venv/Gitea/网络故障)→ 在该仓库创建 Issue 指派 jiangwei-infra(见下方「需要创建 Issue 时」),label 必须包含 type/infrastructure",
"提交 action reportPOST http://localhost:8083/api/projects/_toolchain/tasks/<task_id>/commentscomment_type=action_report)— 报告中说明判断的原因类型和执行的操作",
"修复失败的测试",
"push → CI 自动重跑",
"提交 action reportPOST http://localhost:8083/api/projects/_toolchain/tasks/<task_id>/commentscomment_type=action_report",
],
context_data={
"pr_number": issue_number,
-14
View File
@@ -166,19 +166,6 @@ class ToolchainApiSection:
"",
"⚠️ 不要使用 Mail API(飞鸽传书)。所有协作通过 Gitea 留痕。",
"",
"### 需要创建 Issue 时",
"",
"如果步骤中要求创建 Issue 指派他人(如 jiangwei-infra):",
"```bash",
f'curl -s -X POST "{_GITEA_BASE}/repos/{{repo}}/issues" \\',
' -H "Authorization: token <your-token>" \\',
' -H "Content-Type: application/json" \\',
' -d \'{"title": "[moz] infra: 简述问题", "body": "## 问题描述\\n\\n<简要描述问题现象>\\n\\n## 错误来源\\n\\n- 仓库: <repo>\\n- PR/Commit: <链接>\\n- CI/Deploy run: <Gitea Actions 页面链接>\\n\\n## 日志关键片段\\n\\n```<错误日志摘要>```\\n\\n## 判断依据\\n\\n<为什么判断为基础设施问题>", "assignees": ["jiangwei-infra"], "labels": [<label_id>]}\'',
"```",
"",
"⚠️ Issue body 必须包含错误来源链接(PR/Commit + CI run),让排查者能直接看到全貌。",
"⚠️ label 数字 ID 先 GET /repos/{repo}/labels 查询 type/infrastructure 对应的 ID。",
"",
]
return "\n".join(lines)
@@ -231,7 +218,6 @@ class ToolchainConstraintsSection:
'| “我已经知道了” | ❌ 知道不等于执行。执行步骤 + 提交 action report 才算完成 |',
'| “步骤太多了,选几个做就行” | ❌ 错!必须逐条执行,不可跳过 |',
'| “这个步骤不适用于当前情况” | ❌ 如果确实不适用,在 action report 中说明原因,但其他步骤必须执行 |',
'| “CI/部署失败不是我代码的问题,我什么也不用做” | ❌ 错!即使是基础设施问题,你也必须创建 Issue 指派 jiangwei-infrabody 含错误来源链接 + 日志 + 判断依据),并在 action report 中说明。不能只报告“不是我的问题”就完事 |',
"",
]
return "\n".join(lines)
-70
View File
@@ -523,73 +523,3 @@ class TestFullPromptBuild:
# Must have constraints with Red Flags
assert "Red Flags" in prompt
assert "强制要求" in prompt
# ---------------------------------------------------------------------------
# §17 v2: CI/deploy failure branching + issue label routing + Issue API guidance
# ---------------------------------------------------------------------------
class TestCiFailureBranching:
"""ci_failure steps should include a/b branching guidance."""
def test_ci_failure_steps_contain_branching(self):
source_file = PROJECT_ROOT / "src" / "api" / "toolchain_routes.py"
source = source_file.read_text()
assert '基础设施问题' in source
assert 'type/infrastructure' in source
assert 'jiangwei-infra' in source
class TestDeployFailureBranching:
"""deploy_failure steps should include a/b branching guidance."""
def test_deploy_failure_steps_contain_branching(self):
source_file = PROJECT_ROOT / "src" / "api" / "toolchain_routes.py"
source = source_file.read_text()
count = source.count('基础设施问题(Gitea 不可用')
assert count >= 2, f'Expected >=2 deploy_failure branching, found {count}'
class TestIssueAssignedLabelRouting:
"""issue_assigned handler should route by type/infrastructure label."""
def test_label_check_in_source(self):
source_file = PROJECT_ROOT / "src" / "api" / "toolchain_routes.py"
source = source_file.read_text()
assert 'is_infrastructure' in source
assert 'infrastructure_failure' in source
assert '基础设施 Issue' in source
def test_normal_issue_keeps_coding_steps(self):
source_file = PROJECT_ROOT / "src" / "api" / "toolchain_routes.py"
source = source_file.read_text()
assert '创建分支 fix/' in source
assert 'issue_assigned' in source
class TestToolchainApiIssueGuidance:
"""ToolchainApiSection should include Issue creation guidance."""
def test_has_issue_creation_section(self):
source_file = PROJECT_ROOT / "src" / "daemon" / "toolchain_handler.py"
source = source_file.read_text()
assert "需要创建 Issue 时" in source
assert "/issues" in source
assert "jiangwei-infra" in source
assert "type/infrastructure" in source
def test_issue_body_template_mentions_required_fields(self):
source_file = PROJECT_ROOT / "src" / "daemon" / "toolchain_handler.py"
source = source_file.read_text()
assert "错误来源" in source
assert "判断依据" in source
class TestRedFlagsInfrastructure:
"""Red Flags should include the 'not my code' entry."""
def test_has_infrastructure_red_flag(self):
source_file = PROJECT_ROOT / "src" / "daemon" / "toolchain_handler.py"
source = source_file.read_text()
assert "不是我代码的问题" in source
assert "基础设施问题" in source