i-have-adhd:易读回答、适配器与证据
逐段阅读 i-have-adhd hook:标记、frontmatter 与静默失败
结合十四个离线案例追踪真实分支,包括空规则文件及保留现有 OpenCode 命令。
你将学会
- 从提前退出的分支开始
- 把正则表达式看成明确约定
- 适配器保护部分配置,不保证所有交互
开始前需要
- 基础 Git 与命令行知识
- 能够区分观测行为与未经测试的主张
解释已检查的机制,设计可撤销试验,并在不把风格当正确性的前提下理解证据。
先看结论
- 成功退出与成功注入是不同断言。
- 移除 frontmatter 不等于校验 YAML。
- 通过的边界测试也可能记录不理想行为。
从提前退出的分支开始
Node hook 先确定配置目录并检查 .i-have-adhd-always。没有标记就成功退出且不输出内容;有标记时再从脚本相对路径寻找规则文件,文件不存在同样静默退出。因此,只看宿主状态码无法区分用户主动关闭与安装不完整。
我们的 fixture 创建临时配置目录与合成技能文件,并通过仅指向该目录的 CLAUDE_CONFIG_DIR 启动未改动的固定版本 hook。案例包含无标记、缺少规则、普通正文,以及 LF 和 CRLF frontmatter。执行的是上游真实 JavaScript,但没有助手宿主或语言模型参与。
把正则表达式看成明确约定
替换表达式只移除文件最开头且有结束分隔线的 YAML 风格区块。故意没有闭合的测试文本会保留开头区块,而不是被解析成元数据。这是字符串处理,不是通用 YAML 校验器。末尾处理也只移除换行,不解释规则含义。
两个边界情况值得注意:空文件仍产生启用提示;正文中出现 normal mode 时,hook 会直接打印,而不是把它当关闭命令。两项都通过预期行为测试,但测试通过不代表行为理想。尤其是启用横幅,比“已确认规则正文非空”弱得多。
适配器保护部分配置,不保证所有交互
OpenCode 的配置 hook 只在目录不存在时追加技能目录,并保留已有同名命令。我们在 fixture 中调用两次,确认目录不重复、合成用户命令不被替换。其他案例覆盖空系统提示数组、缺少规则,以及标记仍存在时的新一轮调用。
转换函数向最后一个系统提示字符串追加内容,数组为空时新建一项。它不解析对话退出短语,也不删除选择加入标记。测试为每轮创建新的输出对象,没有反复修改同一个宿主对象,也未验证 OpenCode 生命周期保证。关于重复注入的缺陷报告应明确这条边界。
如何选择
| 比较维度 | 方案 A | 方案 B |
|---|---|---|
| Best when | You need predictable behavior and easy auditing | You need adaptive optimization and have reliable telemetry |
| Main risk | May leave performance on the table | Can become difficult to explain or debug |
实施步骤
- 1
先追踪标记和文件存在性分支。
- 2
同时检查退出码和实际输出。
- 3
隔离测试格式错误和空输入。
- 4
写明 fixture 未覆盖的宿主行为。
可复制示例
// 被检查 hook 使用的模式:字符串处理,不是 YAML 校验。
const strip = text => text.replace(
/^---[^\S\r\n]*\r?\n[\s\S]*?\r?\n---[^\S\r\n]*(?:\r?\n|$)/, ""
);
console.log(strip("---\nname: demo\n---\nRULE"));常见问题
执行的是重新实现的 hook 吗?
不是;fixture 执行固定上游 hook 和适配器,只有规则及宿主对象是合成的。
hook 本身理解退出短语吗?
不理解;它检查标记并输出文本,不是对话状态解析器。
资料来源
- i-have-adhd / hooks/always-on.mjs来源核查 2026-09-12
- i-have-adhd / .opencode/plugins/i-have-adhd.mjs来源核查 2026-09-12
- i-have-adhd / skills/i-have-adhd/SKILL.md来源核查 2026-09-12