Files
sanguo_moziplus_v2/docs/design/14-toolchain-skill-and-deploy.md
T
cfdaily 9161fb4ecd
Deploy / ci (push) Waiting to run
Deploy / deploy (push) Blocked by required conditions
Deploy / notify-deploy-failure (push) Blocked by required conditions
auto-sync: 2026-06-08 12:54:59
2026-06-08 12:54:59 +08:00

606 lines
20 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 工具链 Skill 设计 + 自动部署 + 端到端验证
> **状态**: v1.1 — 仲达评审 M1/M2 修正 + S1-S4 采纳
> **作者**: 庞统(副军师)🐦
> **评审**: 司马懿(仲达)🗡️
> **日期**: 2026-06-08
> **前置**: `13-toolchain-and-dev-workflow.md` v2.2(事件中枢已闭环)
> **定位**: 工具链从"设计完成"到"正式投入使用"的落地设计
---
## §1. 目标
把工具链从设计态推进到可使用态:
1. **L1 TOOLS.md**:每个 Agent 的 TOOLS.md 加入 Gitea API 操作模板,收到 Mail 后开箱即用
2. **L2 Skill 升级**:7 个现有 Skill 对齐事件中枢 + CI 实际运行
3. **deploy.sh + deploy.yml**:补完自动部署的实际脚本
4. **端到端验证**:用 sanguo/moziplus-v2 实验项目验证全链路
---
## §2. 知识体系四层定位
> 来源: `architecture-v3.0.md` §10 BootstrapBuilder
| 层 | 定位 | 载体 | Token | 工具链职责 |
|----|------|------|-------|-----------|
| **L0** | 铁律层 | AGENTS.md / MEMORY.md | ~500 | 不涉及 |
| **L1** | 角色层 | SOUL.md + **TOOLS.md** | ~2000 | **Gitea API 操作模板**Agent 自带,开箱即用) |
| **L2** | 引擎注入 | BootstrapBuilder 注入 Skill 全文 | ~1500 | **7 个 Skill v2**(流程规范,Daemon 确定性注入) |
| **L3** | 被动参考 | Skill descriptionAgent 按需加载 | 按需 | 复用 L2 Skill,不新建 |
**核心原则**
- L1 给操作手段("怎么做"):curl 命令模板、参数说明
- L2 给流程规范("什么时候做什么"):审查清单、分支规范、测试策略
- L3 是 L2 的被动触发版本,不需要单独维护
---
## §3. L1TOOLS.md Gitea 操作模板
### 3.1 设计原则
1. **开箱即用**:收到 Mail 后直接复制粘贴 curl 命令即可执行,不需要查文档
2. **按角色定制**:不是每个 Agent 都需要全套 API,只给该角色需要的
3. **统一格式**:所有模板使用相同的环境变量约定
### 3.2 公共变量约定
每个 Agent 的 TOOLS.md 头部加入:
```markdown
## Gitea 工具链
- **地址**: http://192.168.2.154:3000
- **组织**: sanguo
- **认证**: `Authorization: token $GITEA_TOKEN`(各 Agent 使用自己的 token
- **CI 管理界面**: http://192.168.2.154:3000/sanguo/{repo}/actions
```
### 3.3 按角色模板
#### A. 开发者(张飞/关羽/赵云)— PR 创建 + Merge
```markdown
### 创建 PR
```bash
curl -X POST "http://192.168.2.154:3000/api/v1/repos/sanguo/{repo}/pulls" \
-H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"head": "{branch}",
"base": "main",
"title": "{标题}"
}'
# 返回 .number 即 PR 号
```
### 查看 PR diff
```bash
curl "http://192.168.2.154:3000/api/v1/repos/sanguo/{repo}/pulls/{pr_number}.diff" \
-H "Authorization: token $GITEA_TOKEN"
```
### Merge PRReview 通过后)
```bash
curl -X POST "http://192.168.2.154:3000/api/v1/repos/sanguo/{repo}/pulls/{pr_number}/merge" \
-H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d '{"Do": "merge", "merge_title_field": "Merge PR #{pr_number}"}'
```
### 查看 CI 状态
```bash
curl "http://192.168.2.154:3000/api/v1/repos/sanguo/{repo}/commits/{sha}/status" \
-H "Authorization: token $GITEA_TOKEN"
# .state = "success" | "pending" | "failure" | "error"
```
```
#### B. 审查者(司马懿)— Review 操作
```markdown
### 读取 PR diff
```bash
curl "http://192.168.2.154:3000/api/v1/repos/sanguo/{repo}/pulls/{pr_number}.diff" \
-H "Authorization: token $GITEA_TOKEN"
```
### 查看 PR 改动文件列表
```bash
curl "http://192.168.2.154:3000/api/v1/repos/sanguo/{repo}/pulls/{pr_number}/files" \
-H "Authorization: token $GITEA_TOKEN"
# 每个文件有 .filename, .additions, .deletions, .changes
```
### 提交 Review
```bash
curl -X POST "http://192.168.2.154:3000/api/v1/repos/sanguo/{repo}/pulls/{pr_number}/reviews" \
-H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"body": "{审查意见}",
"event": "APPROVE"
}'
# event 可选: APPROVE | REQUEST_CHANGES | COMMENT
```
### 风险级别判定(自动 + 确认)
规则见 code-review Skill。改动者不能降级,只能维持或升级。
```
#### C. 协调者(庞统)— 全套管理
```markdown
### 创建 Issue + 指派
```bash
curl -X POST "http://192.168.2.154:3000/api/v1/repos/sanguo/{repo}/issues" \
-H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "{标题}",
"body": "{描述}",
"assignees": ["{agent_id}"],
"labels": [1, 2]
}'
# labels 需用数字 ID,先 GET /repos/{owner}/{repo}/labels 查询
```
### 查询仓库 Labels
```bash
curl "http://192.168.2.154:3000/api/v1/repos/sanguo/{repo}/labels" \
-H "Authorization: token $GITEA_TOKEN"
```
### 查询 PR 列表
```bash
curl "http://192.168.2.154:3000/api/v1/repos/sanguo/{repo}/pulls?state=open" \
-H "Authorization: token $GITEA_TOKEN"
```
### 创建 Release
```bash
curl -X POST "http://192.168.2.154:3000/api/v1/repos/sanguo/{repo}/releases" \
-H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"tag_name": "v{version}",
"name": "v{version}",
"body": "{changelog}",
"target_commitish": "main"
}'
```
```
#### D. 平台运维(姜维)— deploy + runner 管理
在开发者模板基础上追加:
```markdown
### 触发手动部署(需要 push 到 main 或手动 re-run
```bash
# Re-run 最近一次 workflow
curl -X POST "http://192.168.2.154:3000/api/v1/repos/sanguo/{repo}/actions/runs/{run_id}/rerun" \
-H "Authorization: token $GITEA_TOKEN"
```
### 查看 deploy-history
```bash
cat ~/.sanguo_projects/{project}/data/deploy-history.jsonl
```
### deploy.sh 规范
见 §5 deploy.sh 设计。所有项目必须遵循统一接口。
```
### 3.4 实施清单
| Agent | TOOLS.md 新增 | 预计行数 |
|-------|--------------|---------|
| zhangfei-dev | 开发者模板(PR/Merge/CI状态) | ~30 行 |
| guanyu-dev | 开发者模板 | ~30 行 |
| zhaoyun-data | 开发者模板 | ~30 行 |
| simayi-challenger | 审查者模板(diff/review/风险判定) | ~40 行 |
| pangtong-fujunshi | 协调者模板(全套管理) | ~50 行 |
| jiangwei-infra | 开发者 + 平台运维模板 | ~45 行 |
---
## §4. L2Skill 升级到 v2
### 4.1 升级原则
1. **不重写已有内容**,在现有 Skill 基础上追加/修改
2. **对齐事件中枢**:每个 Skill 说明在事件中枢链路中的位置
3. **对齐 CI 实际运行**ci.yml/deploy.yml 已有实际配置,Skill 要反映真实情况
4. **对齐 Gitea v1.23.4 限制**:不支持 failure()、concurrency、permissions 等
### 4.2 升级内容
#### git-workflow(小改动)
| 改动 | 说明 |
|------|------|
| 追加"事件中枢集成"节 | PR 创建 → Gitea Webhook → 中枢通知司马懿 → Review → 中枢通知作者 → Merge → deploy.yml 自动触发 |
| 追加"CI 自动触发"说明 | push 非 main 分支自动触发 ci.ymlpush main 自动触发 deploy.yml |
| 追加"分支感知"强化 | Agent spawn 后必须 `git branch --show-current`,确认分支正确 |
#### code-review(中等改动)
| 改动 | 说明 |
|------|------|
| 追加"事件中枢触发"节 | 收到 Mail → 读 PR diff → 审查 → 提交 Review → Webhook 自动通知作者 |
| 更新风险判定规则 | 对齐 §6.1 实际规则(按文件路径自动判定 + 只升不降) |
| 追加 Gitea Review API 操作 | curl 模板(和 L1 TOOLS.md 一致,这里放流程说明) |
| 追加审查结论格式 | APPROVE / REQUEST_CHANGES 的标准格式 |
#### testing-workflow(小改动)
| 改动 | 说明 |
|------|------|
| 追加"CI 集成"节 | UT 在 CI 自动跑(ci.yml test job)、coverage 在 deploy.yml ci job 跑 |
| 追加"E2E 触发方式" | 通过 e2e.yml 手动触发或 `RUN_INTEGRATION=1 pytest` 本地跑 |
| 追加"测试数据隔离" | CI 使用临时 venv + 临时 SQLite + 临时端口 |
#### bugfix-workflow(小改动)
| 改动 | 说明 |
|------|------|
| 追加"事件中枢链路"节 | Bug Issue 创建/指派 → 中枢发 Mail → 修复 → PR → CI → Review → merge |
| 追加"CI 验证"步骤 | 修复后必须等 CI 通过再创建 PR |
#### hotfix-workflow(小改动)
| 改动 | 说明 |
|------|------|
| 追加"CI 自动跑"说明 | hotfix push main → deploy.yml 自动跑 CI + 部署 |
| 追加"失败自动创建 Issue" | deploy.yml notify-on-failure 已实现 |
| 更新 24h 复盘流程 | 复盘结论写到 Issue 评论中 |
#### ci-cd-ops(重写)
| 改动 | 说明 |
|------|------|
| 重写为 v2 | 对齐实际 ci.yml/deploy.yml 结构 |
| 新增 Gitea v1.23.4 限制清单 | 不支持 failure()/concurrency/permissions 等,workaround 方案 |
| 新增覆盖率渐进策略 | P1 只报告 → P2 40% 阈值 → P3 60% 阈值 |
| 新增 deploy.sh 规范 | 统一接口:--version / --source / --target / --health-check / --rollback |
| 新增 CI secret 配置 | CI_TOKEN 作为 repository secret 配置 |
#### release-workflow(中等改动)
| 改动 | 说明 |
|------|------|
| 追加"自动部署触发" | tag 创建 → deploy.yml 自动触发 |
| 追加 deploy-history.jsonl 规范 | 每次 deploy 记录 tag + commit + 时间戳 |
| 更新 schema 变更规范 | 向前兼容 Checklist(加列不加删、默认值、迁移脚本) |
### 4.3 不新建 Skill
现有 7 个 Skill 覆盖所有工具链流程。不需要为事件中枢、CI 操作新建 Skill——这些流程固化在 Mail 模板(§15.5)中,Skill 只提供共通知能。
### 4.4 实施清单
| Skill | 改动级别 | 预计改动行数 |
|-------|---------|------------|
| git-workflow | 小 | +15 行 |
| code-review | 中 | +40 行 |
| testing-workflow | 小 | +20 行 |
| bugfix-workflow | 小 | +15 行 |
| hotfix-workflow | 小 | +15 行 |
| ci-cd-ops | 重写 | ~120 行(原 114 行) |
| release-workflow | 中 | +30 行 |
---
## §5. deploy.sh + deploy.yml 补完
### 5.1 deploy.sh 统一接口
每个项目的 `scripts/deploy.sh` 必须遵循以下接口:
```bash
#!/bin/bash
# scripts/deploy.sh — 项目部署脚本
# 用法:
# bash scripts/deploy.sh --version # 显示当前版本
# bash scripts/deploy.sh --source=DIR --target=DIR --health-check # 部署
# bash scripts/deploy.sh --rollback # 回滚到上一版本
set -euo pipefail
SOURCE_DIR=""
TARGET_DIR=""
HEALTH_CHECK=false
ACTION="deploy"
for arg in "$@"; do
case $arg in
--version) ACTION="version" ;;
--source=*) SOURCE_DIR="${arg#*=}" ;;
--target=*) TARGET_DIR="${arg#*=}" ;;
--health-check) HEALTH_CHECK=true ;;
--rollback) ACTION="rollback" ;;
esac
done
PROJECT_NAME="{project_name}"
DEPLOY_HISTORY="{target_dir}/data/deploy-history.jsonl"
version() {
echo "${PROJECT_NAME} deploy version: $(date -u +%Y-%m-%dT%H:%M:%SZ)"
}
deploy() {
echo "=== Deploying ${PROJECT_NAME} ==="
echo "Source: ${SOURCE_DIR}"
echo "Target: ${TARGET_DIR}"
# 1. 同步文件(排除不需要部署的)
# ⚠️ --delete 会删除目标中源没有的文件,必须排除 data/(生产数据)
rsync -av --delete \
--exclude='.git' \
--exclude='__pycache__' \
--exclude='.venv' \
--exclude='data' \
--exclude='tests' \
--exclude='docs' \
--exclude='.gitea' \
--exclude='node_modules' \
"${SOURCE_DIR}/" "${TARGET_DIR}/"
# 2. 安装依赖
if [ -f "${TARGET_DIR}/pyproject.toml" ]; then
cd "${TARGET_DIR}"
python3 -m venv .venv
.venv/bin/pip install --quiet -e ".[dev]" 2>/dev/null || \
.venv/bin/pip install --quiet -e . 2>/dev/null || true
fi
# 3. 重启服务
if command -v pm2 &>/dev/null; then
pm2 restart ${PROJECT_NAME} 2>/dev/null || true
fi
# 4. 健康检查
if [ "$HEALTH_CHECK" = true ]; then
sleep 3
curl -sf http://localhost:8083/api/health && echo " ✓" || {
echo " ✗ Health check failed!"
exit 1
}
fi
# 5. 记录版本(rollback 时可通过 DEPLOY_OVERRIDE_COMMIT 覆盖)
local commit_hash
if [ -n "${DEPLOY_OVERRIDE_COMMIT:-}" ]; then
commit_hash="${DEPLOY_OVERRIDE_COMMIT}"
else
commit_hash=$(cd "${SOURCE_DIR}" && git rev-parse --short HEAD 2>/dev/null || echo "unknown")
fi
local timestamp
timestamp=$(date -u +%Y-%m-%dT%H:%M:%SZ)
echo "{\"timestamp\": \"${timestamp}\", \"commit\": \"${commit_hash}\", \"source\": \"${SOURCE_DIR}\"}" >> "${DEPLOY_HISTORY}"
# 保留最近 10 条
tail -10 "${DEPLOY_HISTORY}" > "${DEPLOY_HISTORY}.tmp" && mv "${DEPLOY_HISTORY}.tmp" "${DEPLOY_HISTORY}"
echo "=== Deploy complete: ${commit_hash} at ${timestamp} ==="
}
rollback() {
if [ ! -f "${DEPLOY_HISTORY}" ]; then
echo "No deploy history, cannot rollback"
exit 1
fi
# 读取倒数第二行的 commit(不依赖 SOURCE_DIR 的 git 状态)
local prev_line
prev_line=$(tail -2 "${DEPLOY_HISTORY}" | head -1)
local prev_commit
local prev_source
prev_commit=$(echo "${prev_line}" | python3 -c "import sys,json; print(json.load(sys.stdin)['commit'])" 2>/dev/null)
prev_source=$(echo "${prev_line}" | python3 -c "import sys,json; print(json.load(sys.stdin).get('source',''))" 2>/dev/null)
if [ -z "${prev_commit}" ] || [ "${prev_commit}" = "unknown" ]; then
echo "Cannot determine previous version"
exit 1
fi
echo "=== Rolling back to ${prev_commit} ==="
# checkout 到指定 commit,部署,然后回到 main
cd "${SOURCE_DIR}"
local current_branch
current_branch=$(git branch --show-current)
git checkout "${prev_commit}"
# 部署时明确传 commit hash,不依赖 HEAD
DEPLOY_OVERRIDE_COMMIT="${prev_commit}" deploy
git checkout "${current_branch:-main}"
}
case $ACTION in
version) version ;;
deploy) deploy ;;
rollback) rollback ;;
esac
```
### 5.2 deploy.yml 更新
替换当前 placeholder
```yaml
deploy:
runs-on: macos-arm64
needs: ci
steps:
- uses: actions/checkout@v4
- name: Deploy
env:
CI_TOKEN: ${{ secrets.CI_TOKEN }}
run: |
bash scripts/deploy.sh --source="$GITHUB_WORKSPACE" \
--target="$HOME/.sanguo_projects/sanguo_moziplus_v2" \
--health-check
- name: Rollback on failure
if: always()
env:
CI_TOKEN: ${{ secrets.CI_TOKEN }}
run: |
STATUS=$(curl -sf \
-H "Authorization: token $CI_TOKEN" \
"${{ gitea.api_url }}/repos/${{ gitea.repository }}/commits/${{ gitea.sha }}/status" \
| python3 -c "import sys,json; print(json.load(sys.stdin).get('state',''))" 2>/dev/null || echo "")
if [ "$STATUS" != "success" ]; then
echo "Deploy failed, rolling back..."
bash scripts/deploy.sh --rollback || echo "Rollback failed, manual intervention needed"
fi
```
### 5.3 实施清单
| # | 内容 | 文件 | 说明 |
|---|------|------|------|
| D1 | 创建 deploy.sh | moziplus-v2 `scripts/deploy.sh` | 从模板创建,项目名填 sanguo_moziplus_v2 |
| D2 | 更新 deploy.yml | moziplus-v2 `.gitea/workflows/deploy.yml` | 替换 placeholder |
| D3 | 同步到 Gitea | push 到 moziplus-v2 | 触发 CI 验证 |
---
## §6. 端到端验证:sanguo/moziplus-v2 实验项目
### 6.1 为什么用实验项目
- moziplus-v2 主项目已有正式数据(黑板项目、Mail、Task),不适合做破坏性验证
- sanguo/moziplus-v2 当前是空项目(只有 README.md + .gitea/workflows),可以随意实验
### 6.2 验证场景
| 场景 | 操作 | 预期结果 |
|------|------|---------|
| **S1: CI 触发** | push 分支到实验项目 | ci.yml 自动跑 lint + test |
| **S2: PR Review 流程** | 创建 PR → 中枢 Mail → 司马懿 Review → 中枢通知作者 | 全链路 Mail 通知 |
| **S3: CI 失败通知** | push 含 lint 错误的代码 | ci.yml 失败 → 写 PR 评论 → 中枢发 Mail |
| **S4: 部署流程** | merge PR → push main | deploy.yml 自动跑 + 部署 + 健康检查 |
| **S5: Issue 指派** | 创建 Issue 并指派 | 中枢发 Mail 给被指派人 |
| **S6: 幂等验证** | 重复触发同一 delivery_id Webhook | 第二次返回 200 duplicate,不创建重复 Mail |
### 6.3 实验项目 CI 配置
从 moziplus-v2 的 ci.yml 精简,实验项目只需要基本验证:
```yaml
name: CI
on:
push:
branches: ['**', '!main']
pull_request:
types: [opened, synchronize]
jobs:
lint:
runs-on: macos-arm64
steps:
- uses: actions/checkout@v4
- run: echo "lint placeholder"
test:
runs-on: macos-arm64
needs: lint
steps:
- uses: actions/checkout@v4
- run: echo "test placeholder"
```
---
## §7. 覆盖率渐进策略
### 7.1 P1 阶段(启用后 2 周)— 只报告不阻断
**零改动**。当前 deploy.yml 的 ci job 已包含 `--cov=src --cov-report=term-missing`push main 时自动跑)。
注意:ci.yml(非 main 分支)没有 coverage 配置——快速门控不需要覆盖率,这是有意为之。
收集基线数据后决定 P2 阈值。
### 7.2 后续阶段(仅设计,暂不实施)
| 阶段 | 时间 | 策略 | 触发方式 |
|------|------|------|---------|
| P2 | 启用后 1 月 | 40% 阈值,低于警告不阻断 | ci.yml 加 coverage threshold check |
| P3 | 启用后 2 月+ | 60% 阈值,低于阻断 | ci.yml 加 `exit 1` |
---
## §8. 前端展示
### 8.1 Gitea 自带管理界面
Gitea v1.23.4 自带完整的 CI 管理界面:
| 功能 | URL |
|------|-----|
| CI Runs 列表 | `http://192.168.2.154:3000/sanguo/{repo}/actions` |
| 单次 Run 日志 | `http://192.168.2.154:3000/sanguo/{repo}/actions/runs/{id}` |
| PR CI Status | PR 页面自动显示 CI 状态徽章 |
| Webhook 管理 | 仓库 Settings → Webhooks |
**不需要自己做 CI 前端。**
### 8.2 moziplus v2 前端展示
工具链事件的 Mail 通知已在 moziplus v2 前端展示(Mail 列表页)。
如果未来要加,唯一值得做的是:在 moziplus 前端加一个「工具链状态」面板,聚合展示各仓库最近 CI 状态。这是 P4,不阻塞使用。
---
## §9. 实施路线
| 优先级 | 内容 | 耗时 | 前置 |
|--------|------|------|------|
| **P1** | L1 TOOLS.md6 个 Agent | 2h | 无 |
| **P1** | L2 Skill 升级(7 个) | 1d | 无 |
| **P2** | deploy.sh + deploy.yml | 2h | P1 Skill 升级(ci-cd-ops 定义了 deploy.sh 规范) |
| **P3** | sanguo/moziplus-v2 端到端验证 | 2h | P1 + P2 |
| **P4** | 前端工具链状态面板 | 按需 | 不阻塞 |
---
## §10. 前置条件 Checklist
工具链投入使用前必须确认:
| # | 条件 | 状态 | 谁确认 |
|---|------|------|--------|
| 1 | act-runner 已注册且 label = `macos-arm64` | ✅ CI 已跑过 24 次 | 已确认 |
| 2 | Gitea repository secrets 已配置(CI_TOKEN | ⚠️ 需确认 | 姜维 |
| 3 | Gitea 组织级 Webhook 已启用(Hook ID=28 | ✅ 已确认 | 已确认 |
| 4 | 各 Agent 的 GITEA_TOKEN 环境变量 | ⚠️ 待分配 | 庞统协调 |
| 5 | main 分支保护规则(Review 才能 merge | ⚠️ 需确认 | 姜维 |
| 6 | 禁止在 daemon 运行时跑全量 E2E | ✅ 已警告司马懿 | 已确认 |
> 第 5 点很关键——如果 main 分支没有保护规则,开发者可以直接 push main 跳过 Review。
---
## §11. 评审记录
### v1.0 → v1.1 修订清单(仲达评审)
| 编号 | 类型 | 问题 | 修订内容 |
|------|------|------|----------|
| M1 | 必须修 | rsync --delete 会删 data/ | §5.1 --exclude 加 `data` + `node_modules` |
| M2 | 必须修 | runs-on 与实际环境不一致 | 实际 ci.yml/deploy.yml 已用 `macos-arm64`,CI 已跑通,属仲达误判。文档 §6.3 已明确说明 |
| S1 | 建议 | rollback commit 获取有竞态 | §5.1 rollback 改用 DEPLOY_OVERRIDE_COMMIT 显式传递,不依赖 git HEAD |
| S2 | 建议 | pip install 缺 lock file | 采纳但 P3,当前单一部署环境风险低 |
| S3 | 建议 | 缺前置条件 checklist | 新增 §10 前置条件 Checklist |
| S4 | 建议 | 验证场景补 S6 幂等 | §6.2 新增 S6 幂等验证场景 |
| — | 评审 | 庞统模板缺关闭 Issue curl | §3.3 C 节补关闭 Issue 模板 |
| — | 评审 | testing-workflow 加广播风暴禁止 | §4.2 testing-workflow 补充约束 |
| — | 评审 | ci-cd-ops 行数估算措辞 | 修正:重写后预计 ~120 行(原 114 行) |
| — | 评审 | 覆盖率 P1 前提需确认 | §7.1 明确指出 deploy.yml 已有 coverageci.yml 有意不加 |