5b65ed9579
按草案逐条落到正本,并把三处已知错误的口径改回: ① 测试语义:删掉"单测跑的是构建产物,不是源码"这条被过度推广的说法。 只有"跑产物"的套件(端到端 / 契约 / 产物自检)才必须排在构建之后; 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 复查,旧口径只在"说明它已被改掉"的上下文里出现。
138 lines
9.0 KiB
Markdown
138 lines
9.0 KiB
Markdown
# 应用机制:让规范在**以后所有工程**里默认生效
|
||
|
||
> 目标不是"改造现有 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` 的**部署副本**,要能逐字节比对。 |