Files
eng-standards-main/05-应用机制-让规范在以后所有工程生效.md
姚章浩 5b65ed9579 docs: 正本与 Runbook/接入文档口径同步(测试语义、CI-CD 分离、门禁唯一入口、必需检查清单)
按草案逐条落到正本,并把三处已知错误的口径改回:

① 测试语义:删掉"单测跑的是构建产物,不是源码"这条被过度推广的说法。
   只有"跑产物"的套件(端到端 / 契约 / 产物自检)才必须排在构建之后;
   go test 自己编译测试程序、pytest 直读源码、vitest 默认也跑源码。
   写错这条的代价是给每个套件加假依赖、拖慢门禁并制造假故障。T8 同步改。
② CI 与 CD 分离:触发表删掉"推默认分支 → 自动部署测试环境",作业划分表删掉 deploy:test 行,
   §4.6 标注为"项目自己的 CD、不属于通用 CI",速查表同步。
③ 门禁入口:统一为 make verify(名字可不同,但 AGENTS/Runbook/CI 必须指同一个),
   §3.1、§8 清单、§9 速查表一致。
④ 新增 §4.8「必需检查清单与结果口径」:10 项必需检查的判据表 + 三条结果口径
   (失败即停但汇总照做、not_run/skipped 不算过、汇总故障不能报绿),
   以及预览/通知作为旁路的规则。
⑤ 接入文档:修掉"直推也拦得住"这句错口径,并写明接入器不再自动合并、
   --merge-pr 会先核对状态;试点记录里那一步标注为"当时的自动合并行为已改"。
⑥ 03/04/05 里的同源表述一并同步(生成物 jobs 与假成功占位的判据)。

验证:本批 18 处精确替换在脚本里逐处断言"恰好命中 1 次"(DRY-RUN 先过一遍再应用);
替换后全仓 grep 复查,旧口径只在"说明它已被改掉"的上下文里出现。
2026-10-12 00:12:06 +08:00

138 lines
9.0 KiB
Markdown
Raw Permalink 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.
# 应用机制:让规范在**以后所有工程**里默认生效
> 目标不是"改造现有 7 个仓",而是"以后每起一个工程,默认就带着规范跑"。
> 这份文件写的是**机制**,不是条款 —— 条款在 `01-规范`。
## 1. 先纠一个常见做法(Hermes 的实际行为)
Hermes 注入项目上下文的机制(官方 reference `project-context-files.md`):
| 文件 | 发现方式 | 说明 |
|---|---|---|
| `.hermes.md` / `HERMES.md` | 从 cwd **向上走到 git root** | 想要层级继承(根 + 子包覆写)时用;**不会**从 `~` 泄漏进各工程(git root 是边界) |
| `AGENTS.md` / `agents.md` | **只看 cwd**,父/子目录的副本不读 | 想让 Codex / Claude Code / OpenCode 也读到同一份时用 |
| `CLAUDE.md` / `.cursorrules` | 只看 cwd | 同上,别的 agent 的口味 |
三条硬事实:
1. **每会话只加载一个**(first match wins)。
2. **每个文件上限 20,000 字符**,超出**头尾截断**(中间丢,带 `[...truncated...]` 标记)。
⇒ 正本 37 KB **不能**当成项目上下文文件,它必须留在仓里、由技能引用。
3. ⚠️ **不要把规则放 `~/.hermes/AGENTS.md`**:它只在 cwd 正好是 `~/.hermes` 时加载,对"所有工程"作用为零。
官方给的跨项目载体只有两个:`SOUL.md`(`$HERMES_HOME`,**定位是身份**,不是项目规则)或**装技能**。
## 2. 三个渠道(各司其职,不要相互替代)
| 渠道 | 载体 | 覆盖范围 | 加载时机 | 能放什么 |
|---|---|---|---|---|
| **A 技能** | `~/.hermes/skills/devops/eng-standards/SKILL.md` | **所有工程、所有会话** | 按需(任务相关时自动加载) | 操作规则全文(当前 10.7 KB) |
| **B 仓内指针** | 各仓 `AGENTS.md`(跨 agent 可移植)**或** `.hermes.md`(Hermes 专属、可向上继承) | 该仓及其子树 | cwd 命中时**自动注入** | **只放指针**(20 KB 预算) |
| **C 生成器 + 守门** | `scripts/new-project.sh` + CI 里的守门步骤 | 新工程默认带 / 没接的仓会红 | 建仓时 / 每次 CI | 代码 |
**为什么 A 是核心**:文档只有"有人去读"这一个渠道。技能出现在**每个会话的技能清单**里,做 git / 提交 / CI / 发版 / 新工程这类任务时被自动加载 —— 这才是"以后所有工程"的自动性来源,而且**零配置**。
**为什么 B 不能省**(三条,缺一条都要还):
1. 评审 MR/PR 时能看到依据(规范在仓里可见,不是在某个人的 home 目录里)。
2. **别的 agent 读的是 `AGENTS.md`** —— Codex / Claude Code / OpenCode 不读 Hermes 技能。你的工作流里这三种都在用。
3. 读不到技能的环境(别的机器、CI 里的 agent)仍然有入口。
**为什么 C 决定它是"建议"还是"门禁"**:A、B 都是"让人/代理知道",只有 C 让违规**过不去**。
## 3. 已经配好的(今天起就生效)
| 件 | 位置 | 状态 |
|---|---|---|
| 技能 A | `~/.hermes/skills/devops/eng-standards/SKILL.md` | ✅ 已装(10.7 KB,描述 `Use for git/commit/CI-CD/release work in Gitea repos.`) |
| 正本仓 | `zheromiku/eng-standards-main` | ✅ 自包含:`templates/` 里有 `ci_gate.py` / `ci_report.py` 的**逐字节副本**(已 `cmp` 校验) |
| 生成器 C | `~/eng-standards/scripts/new-project.sh` | ✅ 已端到端测过(见 §6) |
| 本机提交闸门 | `~/.githooks/commit-msg`(`core.hooksPath` 全局) | ✅ **全机生效** —— 这台机器上任何仓库提交都拦 |
## 4. 待配置的(需要你拍板或动手)
| 项 | 为什么要 | 谁来做 |
|---|---|---|
| 各仓 `AGENTS.md` 指针 | 渠道 B;同时让 Codex/Claude Code 也读到 | 跨 6 个仓,属独立动作 —— 等指示 |
| `main` 分支保护 | **默认不开**(正本 §1.3)。真要"谁都不能直推"时才开 | 开发可代做;开了之后记得它的代价:状态检查管不住直推 |
| 守门脚本(Gitea 版 spec-check) | 渠道 C 的另一半:让"没接规范的仓"在 CI 里红 | 我可以写(原稿 `spec-check.mjs` 是 GitLab 口径,直接跑会**假红**) |
| 模板漂移检查 | `templates/ci_gate.py` 与各仓 `.gitea/scripts/ci_gate.py` 会漂移;漂移要有人被吵醒 | 我可以写(逐字节比对 + 反向自检) |
**不建议做**:把规范摘要塞进 `SOUL.md`。官方把 `SOUL.md` 定位为**身份**(它每会话必加载),拿它当项目规则用会污染身份层;而且它一旦变长就挤占预算。要 always-on 的提醒,渠道 A 已经覆盖。
## 5. 起一个新工程(5 步,默认就合规)
```bash
# ① 生成骨架(一条命令,9 个文件)
~/eng-standards/scripts/new-project.sh ~/proj/<工程名> <owner>/<repo> [runner-name]
# ② 首次提交(提交信息闸门会自动校验)
cd ~/proj/<工程名> && git add -A
git commit -F - <<'EOF'
chore(init): 初始化工程骨架(CI + 门禁 + 提交规范)
由 ~/eng-standards/scripts/new-project.sh 生成:提交信息闸门、编译自检、
静态产物预览与微信上报(ci-bridge)。正本见 zheromiku/eng-standards-main。
EOF
# ③ 建远端(网页建仓,**不要**勾"初始化仓库")+ 挂 runner/bridge(幂等)
git remote add origin https://gitea.zheromiku.top/<owner>/<repo>.git && git push -u origin main
bash /srv/aiball/runner/attach_repo.sh <owner>/<repo> <runner-name>
# ④ (可选)需要"谁都不能直推"时才开分支保护;**默认不开**(正本 §1.3)
# ⑤ 反向自检:推一个故意违规的提交,确认 gate 红、且 build 没跑
```
生成物:`.gitignore`、`Makefile`、`scripts/verify.sh`、`.gitea/workflows/{build.yml,deploy-production.yml}`、
`.gitea/scripts/{ci_gate.py,ci_report.py}`、`AGENTS.md`、`docs/提交规范.md`、`.git`(默认分支 `main`)。
## 6. 生成器的验证记录(不是"设计如此",是真跑过)
| 检查 | 结果 |
|---|---|
| 空目录 → 生成 | ✅ exit 0,9 个文件齐全 |
| 非空目录 → 拒绝 | ✅ exit 1,`❌ 目标目录非空:…(不覆盖任何东西)` |
| `<PROJECT>` 替换 | ✅ 生成物首行 `# demo-svc —— 提交触发的 CI(Gitea Actions)` |
| 生成物 YAML 合法性 | ✅ 生成后解析:`build.yml` jobs=`gate,build`(**无 deploy 作业**,CI-only);`deploy-production.yml` jobs=`guard,publish` |
| 生成物不含假成功占位 | ✅ `grep -c '^ deploy' build.yml` = 0;prod-deploy 的未实现步骤是 `exit 1` |
| AGENTS.md 指针 | ✅ 含 `eng-standards-main` |
| 闸门脚本逐字节一致 | ✅ `ci_gate.py` 3280 B / `ci_report.py` 2700 B |
| 无构建入口时门禁行为 | ✅ exit 1("入口待补,不算全绿"),**不是静默通过** |
| git 默认分支 | ✅ `main` |
⚠️ 生成过程中自己踩了一个已在规范里写过的坑并已修:`scripts/verify.sh` 的日志夹具只建不删(正本 §3.2-5,
`$TMPDIR` 会攒到几万条)—— 改成**成功时删除、失败时保留并打印路径**。
## 7. 已有工程怎么追平(不做重构,只补三样)
```bash
cd <已有工程>
# ① 补忽略规则与门禁入口(从正本仓拷,不要就地重写)
cp ~/eng-standards/templates/gitignore .gitignore # 按需合并,别覆盖已有的
# 门禁入口:照着 ~/eng-standards/templates 里生成的 scripts/verify.sh 改成本工程真实步骤
# ② 补 CI 骨架(若本仓没有 .gitea/workflows/)
mkdir -p .gitea/workflows .gitea/scripts
cp ~/eng-standards/templates/gitea-build.yml .gitea/workflows/build.yml
cp ~/eng-standards/templates/{ci_gate.py,ci_report.py} .gitea/scripts/
# ③ 补指针:AGENTS.md 里加一行指向 zheromiku/eng-standards-main
```
收紧顺序建议:**先补 CI,再谈分支保护** —— 顺序反了会把 PR 锁死;
而分支保护本身默认不开(正本 §1.3)。渠道 A/B 都是分钟级动作且立刻见效;
再补门禁与守门(决定它是建议还是门禁)。
## 8. 怎么证明它真的生效(这条别跳)
1. **渠道 A**:新开一个会话,随便问"这个仓提交信息什么规范" —— 不重复讲也应该答得出来(技能被加载)。
2. **渠道 B**:在任一已加指针的仓里起会话,问同一个问题 —— `AGENTS.md` 被自动注入。
3. **渠道 C**:推一个违规提交 → 本机 hook 红、CI 的 `gate` 红、且 `build` **没跑**。
4. **平台层**:直接往 `main` push → 被拒。
四条全绿,才叫"规范用起来了"。只做 A 和 B,等于"知道了但拦不住"。
## 9. 单一来源与漂移
- **正本只有一份**:`zheromiku/eng-standards-main`。技能、模板、生成器都是它的**投影**。
- 改了正本 → 同步更新技能体(渠道 A),否则技能里的规则会与正本漂移。
⚠️ 这条目前是**手动的**:技能不是从正本生成的。要么接受"技能是精简版、以正本为准",
要么写一个同步脚本(正本 → 技能体,`--check` 报漂移)。**建议以后者收口**,见 §4 最后一行。
- 各仓 `.gitea/scripts/ci_gate.py` 是 `templates/ci_gate.py` 的**部署副本**,要能逐字节比对。