按草案逐条落到正本,并把三处已知错误的口径改回: ① 测试语义:删掉"单测跑的是构建产物,不是源码"这条被过度推广的说法。 只有"跑产物"的套件(端到端 / 契约 / 产物自检)才必须排在构建之后; 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 复查,旧口径只在"说明它已被改掉"的上下文里出现。
9.0 KiB
应用机制:让规范在以后所有工程里默认生效
目标不是"改造现有 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 的口味 |
三条硬事实:
- 每会话只加载一个(first match wins)。
- 每个文件上限 20,000 字符,超出头尾截断(中间丢,带
[...truncated...]标记)。 ⇒ 正本 37 KB 不能当成项目上下文文件,它必须留在仓里、由技能引用。 - ⚠️ 不要把规则放
~/.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 不能省(三条,缺一条都要还):
- 评审 MR/PR 时能看到依据(规范在仓里可见,不是在某个人的 home 目录里)。
- 别的 agent 读的是
AGENTS.md—— Codex / Claude Code / OpenCode 不读 Hermes 技能。你的工作流里这三种都在用。 - 读不到技能的环境(别的机器、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 步,默认就合规)
# ① 生成骨架(一条命令,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. 已有工程怎么追平(不做重构,只补三样)
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. 怎么证明它真的生效(这条别跳)
- 渠道 A:新开一个会话,随便问"这个仓提交信息什么规范" —— 不重复讲也应该答得出来(技能被加载)。
- 渠道 B:在任一已加指针的仓里起会话,问同一个问题 ——
AGENTS.md被自动注入。 - 渠道 C:推一个违规提交 → 本机 hook 红、CI 的
gate红、且build没跑。 - 平台层:直接往
mainpush → 被拒。
四条全绿,才叫"规范用起来了"。只做 A 和 B,等于"知道了但拦不住"。
9. 单一来源与漂移
- 正本只有一份:
zheromiku/eng-standards-main。技能、模板、生成器都是它的投影。 - 改了正本 → 同步更新技能体(渠道 A),否则技能里的规则会与正本漂移。
⚠️ 这条目前是手动的:技能不是从正本生成的。要么接受"技能是精简版、以正本为准",
要么写一个同步脚本(正本 → 技能体,
--check报漂移)。建议以后者收口,见 §4 最后一行。 - 各仓
.gitea/scripts/ci_gate.py是templates/ci_gate.py的部署副本,要能逐字节比对。