# 待配置事项清单 > 每项:**现状(已核实)→ 要做什么 → 为什么 → 怎么验证 → 谁来做**。 > 优先级:**P0** = 不做则规范形同虚设;**P1** = 影响发布可靠性;**P2** = 一致性/卫生。 > 现状全部来自本次实测(命令在括注里)。 > > ⚠️ 本清单只讲"还差什么";**"怎么让它以后默认生效"(三渠道 + 新工程 5 步)见 `05-应用机制-让规范在以后所有工程生效.md`** —— 别把两份读串。 --- ## P0 ### 1. 分支保护 —— **已定:默认不开**(不需要动) - **决定**:按原稿口径,`main` **不受保护**,所有改动直接进 `main`(正本 §1.1 / §1.3)。 - **现状**:曾给 `Weknora/knowledge-governance` 开过一次(禁直推 + 强制 `build / build (push)`), **已关掉**;7 个仓现在 `GET /repos/{r}/branch_protections` 全为 `[]`。 - **这条知识别丢**:将来真需要"谁都不能直推"时,开保护**前**必须做 `06-接入既有工程.md` §2 的体检 —— **盲目勾"必须状态检查通过"会让 PR 永远等一个不会出现的检查**。判据仍然有效,只是默认不用它。 - **可逆**:开/关都是一次 API 调用或网页点一下,不涉及数据。 ### 2. `knowledge-adapter-service` 的工作流不在 `main` 上 - **现状**:`main` 的 `.gitea/workflows/` **不存在**;`build.yml` 只在 `ci/setup` 分支(`GET .../contents/.gitea/workflows?ref=ci/setup` → 200,`ref=main` → 404)。仓库已有 `runner-weknora-ka-01`。 - **要做什么**:把 `.gitea/workflows/build.yml` + `.gitea/scripts/{ci_gate.py,ci_report.py}` 合到 `main`;关掉/删掉 `ci/setup` 分支。 - **为什么**:现在推 `main` **不触发任何校验**——这个仓库的 `main` 处于"裸奔"状态。 - **怎么验证**:`GET /repos/Weknora/knowledge-adapter-service/contents/.gitea/workflows` 在默认分支返回 `build.yml`;推一个提交,`actions/tasks` 出现新 run。 - **谁来做**:开发(走正常 PR);合并前用 `attach_repo.sh` 的模板拷贝逻辑。 ### 3. 生产发布的"人工确认"落地方式二选一(需在实例上实测) - **现状**:Gitea **没有** GitLab 的 `when: manual` + `manual_confirmation`;生产部署目前**完全不经过 CI**(DobotAI 是人工在生产机 clone + build)。 - **要做什么**: - 方案 A:确认 Gitea 1.26.2 的 Actions 是否支持 `environment:` 及其审批;支持就在生产 workflow 上用。 - 方案 B(不依赖平台):生产 workflow 只 `on.workflow_dispatch`,必填 `sha` + `confirm=deploy-production`,最后一步"切镜像"由本人在生产机执行。 - **为什么**:规范 §5.2 的三层确认里,第二层(参数)与第三层(人)已可落地;第一层要不要平台能力必须先实测,**不能假设**。 - **怎么验证**:在**非生产**仓库建一个 `environment: test-protect` 的最小 workflow 试跑;或直接采用方案 B 并留一条演练记录。 - **谁来做**:本人确认 + 开发实现。 ### 4. "同一份构建产物"的产物落地方式(本环境当前**不满足**) - **现状**:DobotAI 的做法是**在目标机上各自 build**(测试机 build 一次、生产机再 clone 源码 build 一次)——**两份二进制并不逐字节相同**,违反 §5.1。 - **要做什么**: 1. 构建移进 CI(仓库 Runner 上 `docker build`)或至少**只在一台机器 build 一次**; 2. `docker save` 出 `dist/-.tar` + 写 `release-.json`(含 `image_id` / `tar_sha256`); 3. 产物放到一个**两个环境都取得到**的托管点(见第 5 项); 4. 测试与生产都 `docker load` 同一份 tar,并各自断言 `image_id` 相同。 - **为什么**:这是本次规范最核心的新增要求。"测试验收过"必须等于"生产跑的就是那份字节",否则验收结论对生产**无效**。 - **怎么验证**:测试机与生产机各跑 `docker image inspect --format '{{.Id}}'`,两个值**相同**;且都 == 清单 `image_id`。 - **谁来做**:开发(改造构建 + 部署脚本);本人验收。 --- ## P1 ### 5. 构建产物的托管点 - **现状**:`ci-bridge` 的 `/api/ci/publish` 是给**静态网页预览**(tar.gz 解包 + URL)用的,不适合放镜像 tar / 大文件;`/srv/aiball/ci/previews/` 下面只有 3 个目录。DobotAI 的 tar 目前不在任何统一位置。 - **要做什么**:定一个产物目录(建议 `/srv/aiball/ci/artifacts////`,与 bridge 复用同机同 token,按 sha 分目录 + 保留 N 份),或走对象存储/OSS。 - **为什么**:§5.1 要求"生产取同一个 tar",就必须有一个**两个环境都能取到、且可按 sha 寻址**的地方。 - **怎么验证**:从测试机和生产机各 `curl` 一次同一个 `tar_sha256` 地址,都能下到且 `sha256sum` 与清单一致。 - **谁来做**:本人定位置 + 开发接。 ### 6. 生产/测试的部署凭据尚不存在 - **现状**:只有 3 个 Weknora 仓库配了 `CI_BRIDGE_URL`(variable) / `CI_BRIDGE_TOKEN`(secret),**没有任何部署凭据**(`GET /repos/{r}/actions/secrets`)。DobotAI 的部署靠本人在生产机手动执行。 - **要做什么**:按命名后缀建变量/密钥(Gitea 无 environment scope,见规范 §7.1): - Variables:`DEPLOY_TEST_HOST` `DEPLOY_TEST_PORT` `DEPLOY_TEST_USER` `DEPLOY_PROD_HOST` `DEPLOY_PROD_PORT` `DEPLOY_PROD_USER` `ARTIFACT_BASE_URL` - Secrets:`DEPLOY_TEST_SSH_KEY` `DEPLOY_PROD_SSH_KEY` `ARTIFACT_TOKEN` - **为什么**:CI 要有能力"传产物"到目标机;同时 Gitea 无 File 类型 secret,私钥内容整体存 secret、由脚本落盘 0600。 - **怎么验证**:`GET /repos/{r}/actions/variables` 与 `/actions/secrets` 列出全部名字(值不显示);在一个 dry-run workflow 里只在**变量名 + ✓/✗** 层面校验(绝不回显值)。 - **谁来做**:本人在网页/用 `attach_repo.sh` 的接口写入;凭据环节**必须**由本人操作。 ### 7. `Weknora/Enterprise-Knowledge-Base` 接入(含分支收敛) - **现状**:7 条分支(`main` + `release/graph-guard-v0.7.1-r1`、`release/server-running-v0.7.1`、`develop/enterprise-kb`、`chore/db-pool-tuning`、`feature/dingtalk-richtext-image`、`feature/dingtalk-image-only`);**无 workflow、无 Runner**;语言 Go+Vue。 - **要做什么**:分支收敛(该合的合、该删的删)→ 跑规范 §8 的 10 步接入清单。 - **为什么**:长期分支 + `release/*` 正是规范 §1.1 的反模式;且它没有任何校验。 - **怎么验证**:`GET /repos/{r}/branches` 只剩 `main` + 短命分支;`actions/tasks` 有新 run。 - **谁来做**:开发 + 本人确认分支删除范围(删分支不可逆)。 ### 8. Runner 覆盖盘点 - **现状**:Weknora 三仓**各一个**仓库级 Runner(kg/dp/ka);`aiball` 组织级 1 个(`runner-software-01`,覆盖 `protocol-docs` 与 `software-pc`);`Weknora` 组织级 **0 个**。 - **要做什么**:每个新接入仓库都要有**归属该仓库**的 Runner(否则 run 永远 `queued`)。用 `deploy_repo_runner.sh` 起。 - **为什么**:规范 §4.2 —— "run 一直 queued" 的头号原因是仓库没有自己的 Runner,而不是工作流写错。 - **怎么验证**:`GET /repos/{r}/actions/runners` 的 `runners` 非空且 `status=online`。 - **谁来做**:开发(`bash /srv/aiball/runner/deploy_repo_runner.sh `)。 ### 9. `aiball/software-pc` 的 runner 依赖第三方 action - **现状**:`validate.yml` 用 `actions/checkout@v4` + `actions/setup-node@v4`,在 `runner-software-01` 上 run#1 = success(**该 runner 能取 action**);但 Weknora 三仓 runner 上刻意不用。 - **要做什么**:在 `validate.yml` 顶部加注释说明"本 runner 支持取 action";并补上 `npm ci`(现在用 `npm install`,不可重现)。 - **为什么**:规范 §4.3 要求"按 Runner 配置区分"且要写明理由,否则下一个人会照抄到不支持 `uses:` 的 runner 上。 - **怎么验证**:把 `npm install` 改成 `npm ci` 后重跑 run,仍 green。 - **谁来做**:开发。 ### 10. 生产迁移与回滚脚本的"幂等门"复核 - **现状**:DobotAI 已有 `ops/` 下的 `deploy_dobotai_prod.sh` / `rollback_dobotai_prod.sh` / `prod_verify.sh` / `prod_last_turn.sh`(在生产机 `/opt/dobotai/container/ops/`)。 - **要做什么**:对照规范 §5.8 / §5.5 逐条核对:产物 sha 校验、迁移列 COUNT 门、agent 配置 hash CAS、`flock` 互斥、0600 备份。 - **为什么**:规范要求"部分失败后重跑不会双重应用",这是**脚本级**保证,必须在脚本里看到。 - **怎么验证**:每个门都**故意触发**一次(喂一个已存在的列 / 错的 sha),确认脚本**拒绝执行**而不是静默继续。 - **谁来做**:开发(只读复核 + 演练);演练在测试机做。 --- ## P2 ### 11. `aiball/upper-tool`、`zheromiku/protocol-docs` 是空仓 - **现状**:两个仓库 `empty=true`。 - **要做什么**:要么初始化(README + `.gitignore` + 门禁骨架),要么归档。 - **为什么**:空仓出现在仓库列表里,会让人"以为这里该有东西"。 - **怎么验证**:`GET /repos/{r}` 的 `empty=false`,或仓库已归档。 - **谁来做**:本人决定去留。 ### 12. `docs/提交规范.md` 缺失 - **现状**:`~/.githooks/commit-msg` 与 `.gitea/scripts/ci_gate.py` 的提示文案都写着"详见 `docs/提交规范.md`",但仓库里**没有这个文件**。 - **要做什么**:把规范 §2 的内容落成各仓的 `docs/提交规范.md`(或把提示文案改成指向本规范)。 - **为什么**:一条指不到地方的指路,比不指路更费时间(原稿 §2.2 的原话)。 - **怎么验证**:`test -f docs/提交规范.md` 通过;或 grep 提示文案确认已改为可达路径。 - **谁来做**:开发(顺手改)。 ### 13. 规范自身的仓库化(已完成,只剩"各仓加指针") - **现状**:正本已入仓 —— `zheromiku/eng-standards-main`,默认分支 `main`,2 条提交,HEAD `419396f3ce0c`;本地 `~/eng-standards/` 的 `git rev-parse HEAD` 与远端 `ls-remote` 一致。 ⚠️ 仓名带了 `-main` 后缀(原计划写的是 `eng-standards`);文档内 4 处引用已按**实际仓名**改正,不留指不到的指针。 - **要做什么**:~~①建仓~~ ✅ ~~②push~~ ✅;③ 各仓 `AGENTS.md` 加一行指针:`Weknora/{dobotai-platform, knowledge-governance, knowledge-adapter-service, Enterprise-Knowledge-Base}`、`aiball/{software-pc, protocol-docs}`。 - **为什么**:规范要"不用每次重复说一遍",靠的是可被引用的单一来源(原稿 §11)。先前放在 `/srv/aiball/ci/standards/` 下是分类错误 —— 跨仓规范不该挂在单个项目(AI球)的目录里。 - **怎么验证**:`git ls-remote --heads origin main` 的 SHA == 本地 `git rev-parse HEAD`;各仓 `AGENTS.md` 里的指针路径可达。 - **谁来做**:③ 需要**改动 6 个仓库**,属独立动作 —— 等指示,不自行扩围。 ### 14. `aiball` 固件(ESP32-P4)的流水线尚未定义 - **现状**:`/srv/aiball/firmware` 有固件工程,但 Gitea 上**没有对应仓库**;`aiball` 组织下只有 `protocol-docs` / `software-pc` / `upper-tool`。 - **要做什么**:固件入仓后,按同一套 §5.1 建固件流水线:`idf.py build` 一次 → 记录 `.bin` 的 sha256 → 测试机烧录测试版 → **量产/发布烧同一份 `.bin`**。 - **为什么**:固件同样适用"同一份产物"铁律;烧录"只写不回读",所以**产物哈希是唯一可信的同一性证据**(AIxProbe 经验)。 - **怎么验证**:`sha256sum` 两次产物文件一致;烧录日志里的字节数与 `OpenOCD wrote` 一致。 - **谁来做**:本人定仓库归属 + 开发建流水线。 ### 15. `ci-bridge` 的公开地址与实际可达性核对 - **现状**:`config.json` 的 `public_base=http://192.168.50.134:8899`、`public_base_alt=http://100.92.49.78:8899`;本次实测 `127.0.0.1:8899/healthz` 正常(`reports:19, previews:7, notify:true`)。 - **要做什么**:核对 `192.168.50.134` 是否仍是本机当前 LAN 地址(网段变化会让所有通知里的链接失效)。 - **为什么**:报告里给的每个 URL 都必须能 200,否则通知等于没发。 - **怎么验证**:`curl -m 5 http://192.168.50.134:8899/healthz` 与 `curl -m 5 http://100.92.49.78:8899/healthz` 都返回 `ok:true`。 - **谁来做**:本人/开发。 ### 16. 规范守门脚本的 Gitea 版(可选) - **现状**:附件里的 `spec-check.mjs` 是 GitLab 口径(判据含 `glab` 占位符、`.gitlab-ci.yml`、`workflow.rules`),直接拿来自Gitea 环境跑会**假红**。 - **要做什么**:改写判据:`.gitlab-ci.yml` → `.gitea/workflows/*.yml`;`workflow.rules` → `on:` 三类入口;`glab-placeholder` → `giteactl/gitea_api.py` 等价约束;`resource_group` → `flock`。保留 `--self-test` 的反向自检。 - **为什么**:规范的"可执行"部分最好变成退出码(原稿 §11.2),但不改写就会假红,而假红和假绿一样要修。 - **怎么验证**:`--self-test` 造两个夹具(合规全绿、违规每条都红)。 - **谁来做**:开发(本次未做,见任务边界)。 --- ## 不建议做的事(写下来防止被"顺手加上") - ❌ 不要为了能 push 去改 Gitea 凭据/token scope —— 权限没配好要**问人**,自己换 remote/换账号会把"权限没配好"变成"动作做了一半"。 - ❌ 不要把测试环境部署塞回 `build.yml`(CI 流水线只管校验与编译);生产 workflow 就是生产 workflow。 占位作业在填完真实逻辑之前**必须红**,不许"打印 TODO 然后返回成功"。 - ❌ 不要给生产 workflow 设 `concurrency.cancel-in-progress: true`(会取消正在进行的部署,而取消不是回滚)。 - ❌ 不要在生产与测试**同时**跑压测(两服共用同一套 RDS,会扰动生产)。 - ❌ 不要在源码路径里用 `dist` / `data` / `secrets` 这些名字(`.gitignore` 会静默吞掉)。