根因分析:SPR update 错位问题的真正根源
一、现象:spr update 的错位
- AI 遇到
spr update时,不知道是「技能消费者更新」还是「开发者在同步」 - 多次出现 merge 到 main、擅自 git 操作等行为
- 之前的 patch(SKILL.md 加 AI 执行流程)治标不治本
二、架构:三重副本问题
开发仓库 (git 管理)
~/skill-portfolio-report/
│
│ hermes skills install <git-url>
│ → 源适配器 fetch() → git clone/下载
│ → 安全检查 → mv 到 skills 目录
▼
Hermes 技能目录 (无 .git)
/opt/data/skills/financial-services/spr/
│
│ spr update AI 流程的后半段:
│ git pull + cp 同步
▼
用户维护副本
/opt/data/home/skills/financial-services/spr/
核心问题:三重副本 + 同步桥接 = 脆弱的 git 桥模式
三、根因:skill install 的设计假设
hermes skills install 的 fetch() → quarantine → scan → install 链路,设计目标是为 消费者 服务:
| 维度 | 消费者(设计目标) | 开发者(你的场景) |
|---|---|---|
| 需要 clone? | ✅ 需要,否则没代码 | ❌ 已有开发仓库 |
| 技能目录角色 | 只读安装目标 | 开发物的一个副本 |
| git pull 之处 | 不需要 | 开发仓库 |
| 更新方式 | 重新 install | git pull + 同步副本 |
| 仓库所有权 | 别人的 | 自己的 |
结论:同一个 install 流服务两种对立的角色,导致开发仓库和技能目录分离,进一步迫使 spr update 走「git pull → cp 同步」的脆弱桥模式。
四、为什么要有 pull?
fetch() 的工作方式:源适配器从 git URL 下载文件到临时目录(不是 git clone 带 .git),然后 mv 到 skills 目录。这只在消费者场景下有意义。开发者场景下,纯属冗余。
Hermes 的 lock.json 只认 installed 路径,不识别「这个 skill 的源是一个本地目录」——所以没有省掉 pull 的原生支持。
五、三种解决路线
方案 A:符号链接(推荐)
开发仓库 SKILL.md → symlink → skills/.../SKILL.md
- 零副本、零同步
- 开发仓库即 skill 目录
- spr update = git pull(无 cp 步骤)
- 需 Hermes 端改动:skill 加载允许 symlink
方案 B:本地注册(editable mode)
hermes skills register ~/skill-portfolio-report --name spr
- 类似 pip install -e .
- lock.json 标记 type: local,跳过 clone
- 需 Hermes 新增 register 子命令
方案 C:当前妥协
spr update 流程:pull dev → 判断 → 同步 skills → 更新 VERSION → commit
- 脆弱:步骤多、身份混淆、AI 易出错
- 不可靠:git pull Already up to date 时 AI 不知下一步
六、教训
- SKILL.md 补 AI 执行流程是症状修复,不是根因修复。真正的问题是架构层的角色假设冲突
- AI 触发词(trigger)不能同时是 git 操作命令——身份混淆是必然的
- 开发者场景下,技能安装应优先考虑不产生副本的注册模式
七、相关讨论
- 讨论日期:2026-05-28
- 触发:STDD 修复 spr update 错位 bug 时提出的架构质疑
- 后续:方案 A(符号链接)可动手实现,消掉 spr update 一半的 AI 流程