# 应用机制:让规范在**以后所有工程**里默认生效 > 目标不是"改造现有 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/<工程名> / [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//.git && git push -u origin main bash /srv/aiball/runner/attach_repo.sh / # ④ (可选)需要"谁都不能直推"时才开分支保护;**默认不开**(正本 §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,`❌ 目标目录非空:…(不覆盖任何东西)` | | `` 替换 | ✅ 生成物首行 `# 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` 的**部署副本**,要能逐字节比对。