AI编程助手防幻觉实战:追踪器-账本-守卫模式详解
1. 项目概述为AI编码助手戴上“紧箍咒”如果你也用过Claude Code、Cursor这类AI编程助手大概率经历过这种让人哭笑不得又血压飙升的时刻你让它修复一个bug它信誓旦旦地告诉你“已经修复并验证通过”结果你一跑测试发现它压根没运行任何测试所谓的“修复”可能还引入了新问题。或者它声称“文件不存在”但实际上只是它没去搜索。这种AI“幻觉”——即AI自信地陈述未经核实的事实——在复杂的开发任务中尤其致命因为一次错误的“记忆”会成为下一次任务的错误前提错误像滚雪球一样累积。no-hallucination项目就是为了根治这个问题而生的。它不是一个简单的代码检查工具而是一套完整的“认知纪律”强制执行系统。其核心思想非常直接让AI的每一个关键声明都必须有可验证的证据支撑否则就阻止它继续行动。你可以把它想象成给AI配了一位极其严格、只认证据的“审计员”。这位审计员不关心AI“觉得”自己做了什么只关心可追溯的记录。这套系统最初提炼自一个需要多个AI代理协同处理关键任务如知识管理、金融操作的生产环境在那里一句未经证实的“我搞定了”可能导致真实的损失。项目通过三个核心组件构成一个完整的证据闭环/orient定向、守卫钩子Guards、/ship交付。/orient确保每次会话都基于上一次会话留下的、由证据构成的“连续性文件”开始而非模糊的对话记忆守卫钩子在会话中实时监控拦截无证据的声明/ship在会话结束时严格依据git日志和命令输出生成新的连续性文件为下一次会话铺路。这就构建了一个“证据驱动”的工作流将AI的过度自信倾向用机械化的规则锁死。2. 核心设计思路追踪器-账本-守卫模式no-hallucination的威力源于其精巧的底层设计模式追踪器Tracker- 账本Ledger- 守卫Guard。理解这个模式你就能明白它是如何像手术刀一样精确地切除“幻觉”的。2.1 模式的三位一体这个模式模仿了严谨的审计或实验记录过程追踪器Tracker相当于“监控摄像头”或“实验记录员”。它们是钩子Hooks被动地监听AI代理执行的操作。例如当AI运行npm test、grep -r functionName或进行第一次文件编辑时对应的追踪器就会被触发。它的职责是客观记录将事件如命令、参数、时间戳、结果以结构化的方式通常是JSON写入到特定的“账本”文件中。追踪器本身不做任何判断只负责忠实记录证据。账本Ledger相当于“实验日志”或“审计底稿”。它是一个存储在项目.claude/guard-hooks/目录下的文件例如verify-ledger.json。所有追踪器记录的证据都汇聚于此。账本是整个系统的唯一事实来源是守卫进行裁决的依据。它的存在使得AI工作流变得可观测、可复盘。守卫Guard相当于“质检员”或“评审专家”。它们也是钩子但角色是主动的“拦截者”。当AI代理试图做出一个声明如在对话中说“所有测试都通过了”或“我修复了那个bug”时对应的守卫会被触发。守卫会立即去查询相关的账本文件检查证据链是否完整。如果证据缺失例如没有运行测试的记录或没有修复前的问题状态记录守卫就会阻止BLOCKAI的这次响应并要求AI先提供证据。2.2 一个完整的工作流示例假设AI需要修复auth.js中的一个身份验证bug。没有no-hallucination的典型幻觉场景AI直接编辑auth.js。AI在对话中输出“已修复身份验证bug——已验证所有测试通过。”开发者信任AI合并代码然后发现生产环境出问题。回头检查才发现AI根本没运行测试所谓的修复是凭“感觉”写的。有no-hallucination的证据驱动场景AI试图直接编辑auth.js并声明修复。proof-guard和verify-guard被触发。verify-guard检查verify-ledger.json没有发现本次会话中运行测试的记录。结果BLOCK。AI收到提示“你声称修复了问题但未运行任何验证。请先展示问题状态。”AI执行npm test测试失败假设有3个失败用例。verify-tracker自动将此命令及其结果记录到verify-ledger.json。AI编辑auth.js。edit-timestamp追踪器记录下第一次编辑发生的时间。AI再次执行npm test测试通过24/24。verify-tracker再次更新账本。AI现在可以输出“已修复身份验证bug。修复前测试失败3个失败修复后通过24/24。差异auth.js第42行。”proof-guard检查账本发现了“修复前失败”和“修复后通过”的完整证据链。verify-guard检查发现了测试运行记录。结果PASS。声明被允许发送。这个过程强制AI遵循了科学方法观察发现问题→ 假设进行修改→ 实验验证结果→ 结论报告差异。所有步骤都有据可查。实操心得这个模式最巧妙的地方在于它没有试图去“理解”代码或逻辑是否正确——那是AI和开发者的事。它只强制执行“过程正确”。只要过程正确证据链完整即使最终代码有误也大大降低了调试成本因为你可以完整复盘AI的每一步操作和当时的系统状态。3. 守卫钩子详解十一道“防火墙”项目提供了11个开箱即用的钩子构成了多层次的安全网。下面我们深入解析几个核心守卫的工作原理和配置要点。3.1 核心守卫验证、证据与声明verify-guard验证守卫触发时机当AI的响应中包含如“verified”、“tests pass”、“all green”、“check passed”等表明已验证的短语时。检查逻辑查询verify-ledger.json检查当前会话内是否有任何验证类命令如npm test,pytest,go test,curl健康检查的记录。拦截场景AI说“我验证了功能正常”但账本里空空如也。守卫会阻止响应并提示“你声称进行了验证但未找到运行验证命令的记录。请先运行相关检查如测试、lint、健康检查。”配置你可以修改钩子脚本开头的TRIGGERS变量添加你们团队常用的验证话术例如TRIGGERS验证通过|测试通过|检查完毕|all checks passed。proof-guard证据守卫触发时机当AI的响应包含“fixed”、“solved”、“implemented”、“added”等表明已实施变更的短语并且上下文涉及问题修复或功能添加时。检查逻辑这是最严格的守卫之一。它要求一个完整的“前后对比”证据链“前”证据在第一次文件编辑由edit-timestamp记录之前必须有验证命令显示“失败”或“不存在”的状态。“后”证据在编辑之后必须有验证命令显示“成功”或“已解决”的状态。拦截场景AI直接修复并报告成功但没有展示修复前的问题状态。守卫会阻止并提示“你声称修复了问题但缺少修复前的状态证据。请先展示问题例如运行失败的测试再进行修改最后验证结果。”重要性这个守卫直接针对“无中生有”的修复幻觉是保证代码变更质量的关键阀门。claim-guard声明守卫触发时机当AI的响应包含“does not exist”、“no file called”、“找不到”、“没有”等否定存在性的短语时。检查逻辑查询search-ledger.json检查当前会话内是否有相关的搜索命令如find,grep,ls,glob模式匹配记录。拦截场景AI说“项目里没有config.yaml文件”。守卫会检查如果发现AI根本没搜索过就会阻止并提示“你声称某物不存在但未进行搜索。请先使用find、grep或文件浏览进行确认。”配置技巧对于大型项目你可能希望限制搜索范围以避免性能问题。可以通过环境变量GUARD_HOOKS_SEARCH_SCOPES设置搜索路径例如export GUARD_HOOKS_SEARCH_SCOPESsrc/:config/这样守卫会要求AI必须在指定目录内进行过搜索其声明才被接受。3.2 基础设施守卫与交付物追踪build-gate构建门禁触发时机在AI尝试编辑或写入基础设施类文件如package.json,Dockerfile,docker-compose.yml,webpack.config.js,.github/workflows/*之前。检查逻辑这是一个“预检”钩子PreToolUse。它不会检查账本而是会强制中断当前流程要求AI先执行一个调查流程。它会提示AI必须完成1) 调查现状2) 诊断问题3) 审计影响4) 提出方案。只有经过这个步骤后AI才能获得编辑许可。设计目的防止AI对基础设施进行“快速而危险”的修改。很多灾难性的错误都源于对package.json或Dockerfile的一次轻率编辑。这个门禁强制了审慎的决策过程。deliverable-guard交付物守卫与track-deliverable交付物追踪器协作模式这是一个守卫-追踪器组合用于管理AI在项目目录外创建的文件如临时分析报告、架构图、总结文档。工作流程AI在项目外创建文件如/tmp/analysis.md。track-deliverable追踪器检测到此次写入并在deliverable-ledger.json中记录文件路径、大小和哈希。当AI会话即将结束时deliverable-guard被触发。它检查账本中所有被追踪的“外部文件”。守卫会列出这些文件并要求AI对每一个做出决策是将其移入项目并提交/ship会处理还是确认其为临时文件可以删除或是需要将其添加为待办事项Reminder价值解决了AI工作流中一个常见痛点生成的有用产出物散落在各处最终丢失。这个机制确保了所有产出都被主动管理要么纳入版本控制要么被清理要么转化为明确的任务。3.3 钩子健康检查随着项目演进你可能会添加自定义钩子。no-hallucination附带了一个实用的健康检查脚本scripts/hook-health.sh。功能它对比你的.claude/settings.json中注册的钩子与hooks/目录下实际存在的脚本报告三类状态ACTIVE钩子已注册且脚本存在运行正常。STALE钩子在settings.json中注册但脚本文件已被删除。这是一个需要修复的配置错误。ASSUMED钩子脚本存在但触发条件非常罕见如pre-compact,post-compact在检查期间未触发但结构上被认为是正常的。使用方法定期例如每周在项目根目录运行bash scripts/hook-health.sh。使用--project-only参数可以忽略全局钩子设置只检查当前项目。输出示例解读 HOOK HEALTH — 2026-03-30 ACTIVE (9) verify-guard.sh Stop evidence: LEDGER proof-guard.sh Stop evidence: LEDGER ... STALE (1) custom-lint-guard.sh PreToolUse:Edit -- SCRIPT MISSING ASSUMED (2) pre-compact.sh PreCompact rare event — structural OK上面的报告显示custom-lint-guard.sh这个钩子被配置了但脚本丢失你需要要么补充脚本要么从配置中移除它。注意事项钩子的执行顺序和依赖关系需要留心。默认的钩子设计是独立的但如果你创建了有依赖关系的自定义钩子例如一个钩子需要另一个钩子先写入账本你必须确保它们在settings.json中的注册顺序是正确的或者通过共享状态文件进行协调。混乱的钩子顺序可能导致守卫检查时证据还未就绪。4. 技能闭环定向、构建与交付守卫钩子提供了过程控制而/orient和/ship这两个技能则构建了会话生命周期的完整性确保跨会话的上下文传递是基于证据而非记忆。4.1/orient基于证据的会话定向/orient技能在每次会话开始时使用。它的任务是取代人类开发者“我们上次做到哪了”的模糊提问提供一个由数据驱动的、结构化的启动报告。它做了什么读取连续性文件读取由上一个会话的/ship生成的.claude/last-session.md。这是跨会话事实传递的基石。收集实时状态Git状态当前分支、是否有未提交更改、最近提交信息。目标与提醒如果配置了GOALS_FILE和REMINDERS_FILE会读取并显示待办事项和截止日期。静默读取可配置GROUNDING_FILES如README.md,ARCHITECTURE.md在后台读取其内容为AI提供项目背景知识而不占用上下文窗口。生成结构化报告将以上信息整合成一个清晰、简洁的仪表盘输出。“完整版”与“最小版”的选择项目提供两个版本orient最小版核心功能包含连续性文件读取和Git状态。orient-full生产版在最小版基础上预留了多个扩展点你可以轻松取消注释来集成依赖检查npm outdated,pip list --outdated测试套件健康度运行特定测试或检查覆盖率报告构建/CI状态调用CI API获取最新构建结果服务健康度对关键端点进行心跳检查自定义指标如数据库连接数、队列长度配置要点 编辑skills/orient-full/SKILL.md顶部的配置块CONTINUITY_FILE.claude/last-session.md GOALS_FILEproject-goals.md # 指向你的目标跟踪文件 REMINDERS_FILE.claude/reminders.md # 指向你的提醒文件 GROUNDING_FILESREADME.md:ARCHITECTURE.md:TODO.md # 冒号分隔的关键文件GROUNDING_FILES是一个强大但常被忽略的功能。它让AI在会话开始时“默默”阅读这些文件从而在后续对话中能更准确地引用项目结构、待办事项和架构决策显著减少因遗忘项目细节而产生的幻觉。4.2/build基础设施变更的预审门禁/build技能是一个手动触发的“安全开关”。当你或AI准备进行高风险的基础设施变更时比如修改依赖、调整构建配置、更新部署脚本你应该先运行/build。它的四阶段调查流程调查全面收集当前状态。例如对于依赖更新会运行npm outdated并检查CHANGELOG.md。诊断分析潜在影响。这个更新是安全补丁吗是否有破坏性变更哪些模块会受影响审计检查依赖项。是否有测试覆盖CI流水线是否健全回滚计划是什么提议基于以上分析提出具体的、分步骤的变更方案并请求明确的批准。使用场景这不是每次编辑都需要的步骤而是针对那些“牵一发而动全身”的变更。它强制了一个冷静、分析性的决策过程完美地克制了AI或人类在复杂问题前可能出现的“先改了再说”的冲动。4.3/ship生成可审计的会话快照/ship技能在会话结束时使用。它的核心职责是基于客观证据创建连续性文件绝不依赖对话历史的内存。它的工作流程审查Git日志获取本次会话期间的所有提交。这是工作量的主要证据。检查交付物与deliverable-guard联动处理所有在项目外创建的文件。更新目标与提醒根据本次会话的完成情况更新GOALS_FILE和REMINDERS_FILE。生成连续性文件将以下内容写入.claude/last-session.md本次会话的提交摘要。未解决的事项明确列出哪些目标没完成、哪些问题待处理。这是防止任务“消失”的关键。给下个会话的上下文重要的决策理由、临时方案的解释等。例如“选择Sliding Window限流器而非Fixed Window原因见提交abc123的注释。”执行Git操作可选地自动提交使用可配置的提交前缀如“Session close:”和推送。配置要点 编辑skills/ship/SKILL.mdCONTINUITY_FILE.claude/last-session.md GOALS_FILEproject-goals.md PUSH_AFTER_COMMITfalse # 如果你不想自动推送设为false COMMIT_PREFIXSession: # 用于提交信息也用于幂等性检查防止重复提交COMMIT_PREFIX的幂等性检查很实用如果最新提交的信息已经以此前缀开头/ship会认为本次会话已经关闭过从而避免生成重复的连续性文件。实操心得养成以/orient开始、以/ship结束每个重要编码会话的习惯。这不仅仅是给AI用的更是给你自己用的。那个last-session.md文件是你项目的最佳“工作日志”当你一周后回来或者与新队友交接时它的价值无可估量。它记录的不是“AI说了什么”而是“实际发生了什么”。5. 安装与配置实战5.1 环境准备与快速安装系统要求Claude Code任何支持钩子Hooks和技能Skills的版本。这是运行时环境。bash和jq用于执行钩子脚本和解析JSON。macOS和主流Linux发行版通常已预装。Windows用户可通过WSL2获得完整支持。git用于版本控制状态追踪和/ship技能。推荐安装方式一键安装克隆仓库到本地任意位置不一定要在项目内。git clone https://github.com/AlethiaQuizForge/no-hallucination.git ~/tools/no-hallucination进入你的项目目录。cd /path/to/your/project运行安装脚本。根据你的需求选择最小化安装仅核心守卫钩子~/tools/no-hallucination/install.sh完整生产安装包含所有钩子和完整版技能~/tools/no-hallucination/install.sh --full安装脚本会检查jq和git是否存在。在你的项目根目录创建.claude/hooks/和.claude/guard-hooks/账本目录等必要结构。将钩子脚本复制过去并赋予执行权限。尝试合并settings.json。如果项目已存在.claude/settings.json脚本会备份原文件并生成一个合并后的新文件你需要手动核对合并结果。5.2 手动安装与精细配置对于想要更精细控制或已有复杂Claude Code配置的用户手动安装是更好的选择。步骤一复制核心文件# 在你的项目根目录下 mkdir -p .claude/{skills,hooks,guard-hooks} # 复制技能选择其一或都复制 cp -r /path/to/no-hallucination/skills/ship .claude/skills/ cp -r /path/to/no-hallucination/skills/orient-full .claude/skills/orient # 推荐使用完整版 # 复制所有钩子脚本 cp /path/to/no-hallucination/hooks/*.sh .claude/hooks/ chmod x .claude/hooks/*.sh步骤二合并钩子配置这是最关键的一步。你需要编辑项目或全局的~/.claude/settings.json文件。该文件结构大致如下{ hooks: { Stop: [ { command: /absolute/path/to/your/project/.claude/hooks/verify-guard.sh, cwd: /absolute/path/to/your/project }, { command: /absolute/path/to/your/project/.claude/hooks/proof-guard.sh, cwd: /absolute/path/to/your/project } // ... 其他守卫 ], PreToolUse: [ { command: /absolute/path/to/your/project/.claude/hooks/build-gate.sh, cwd: /absolute/path/to/your/project, toolNames: [write_file, edit_file] } ], PreCompact: [ { command: /absolute/path/to/your/project/.claude/hooks/pre-compact.sh, cwd: /absolute/path/to/your/project } ], PostCompact: [ { command: /absolute/path/to/your/project/.claude/hooks/post-compact.sh, cwd: /absolute/path/to/your/project } ] } }cwd参数必须正确它必须是钩子脚本所在项目的绝对路径这样脚本才能正确找到项目根目录下的.claude/guard-hooks/账本目录。toolNames过滤对于build-gate.sh这样的PreToolUse钩子通过toolNames指定它只监听“写文件”和“编辑文件”操作并且脚本内部会进一步过滤文件路径如只针对package.json等基础设施文件。步骤三配置技能分别编辑.claude/skills/orient/SKILL.md和.claude/skills/ship/SKILL.md顶部的配置部分设置好文件路径、目标文件等如前文所述。步骤四测试激活在Claude Code中打开你的项目。输入/orient并回车。你应该能看到一个结构化的启动报告。尝试让AI做一个需要验证的修改。例如告诉它“请检查utils.js里有没有叫formatDate的函数如果没有就添加一个。”观察claim-guard是否生效如果AI直接说“没有这个函数”它应该被阻止并要求先执行搜索如grep -n formatDate utils.js。5.3 多项目管理与全局配置如果你在多个项目中使用Claude Code你有两种策略项目级配置推荐在每个项目根目录下单独安装和配置no-hallucination。这样每个项目的钩子和账本都是独立的互不干扰。只需确保每个项目的.claude/settings.json中的cwd路径指向正确的项目目录。全局钩子配合项目检测可以将钩子脚本放在一个全局位置如~/.claude/global-hooks/并在全局settings.json中注册。但在每个钩子脚本的开头需要添加逻辑来检测当前工作目录是否是一个启用了该系统的项目例如检查是否存在.claude/guard-hooks目录。如果不是则脚本应直接退出exit 0避免在不相关的项目中误触发。这种方式更复杂但便于集中管理钩子更新。避坑指南安装后最常见的失败原因是路径错误。务必检查settings.json中每个钩子的command路径和cwd路径是否正确、是否存在。另一个常见问题是权限确保所有.sh脚本都有执行权限 (chmod x)。如果钩子不触发在Claude Code的设置中打开调试日志查看钩子加载和执行情况。6. 常见问题排查与实战技巧即使配置正确在实际使用中也可能遇到各种情况。下面是一些常见问题的排查思路和从实战中总结的技巧。6.1 钩子不触发或误触发症状AI做出了无证据的声明但守卫没有拦截。检查1钩子是否已加载。在Claude Code中检查设置界面的“Hooks”部分确认你的钩子列表中出现并且状态正常无错误图标。检查2触发短语是否匹配。AI使用的表述可能不在默认的TRIGGERS列表中。例如AI说“搞定测试全绿”而你的verify-guard只匹配“tests pass”。你需要编辑钩子脚本将“全绿”、“通过”等你们团队的习惯用语加入TRIGGERS变量。技巧可以先让钩子脚本将匹配到的消息内容记录到一个调试日志文件中观察AI的实际输出。检查3账本文件权限。确保.claude/guard-hooks/目录及其下的.json文件对运行Claude Code的用户可写。在有些系统上权限问题会导致追踪器无法写入证据。症状钩子过度触发拦截了合理的对话。检查1触发条件是否太宽泛。例如claim-guard的触发短语可能包含了常见单词导致在无关上下文中被触发。尽量使用更具体的短语模式或者为短语添加单词边界匹配如在正则表达式中使用\b。检查2守卫逻辑的“会话”边界。所有守卫默认检查的是“当前会话”内的证据。Claude Code的“会话”如何定义通常是一次对话窗口的生命周期。如果你关闭窗口重开就是一个新会话之前的账本可能不被继承除非你做了持久化处理。no-hallucination的设计是会话内证据链闭环跨会话依赖/orient和/ship。理解这一点可以避免困惑。6.2 证据链不完整导致阻塞症状AI确实做了验证但proof-guard仍然拦截提示缺少“之前”的证据。根因proof-guard要求“在第一次编辑前”有失败证据。如果AI在本次会话中先做了其他无关的编辑那么edit-timestamp记录的时间点就很早。之后当AI去修复另一个bug时在“第一次编辑”之后运行的测试失败记录就不符合“之前”的条件。解决方案会话纪律一个会话尽量只聚焦一个任务。开始新任务时使用/orient刷新或开启一个新的对话窗口。手动重置在开始关键修复前可以手动删除.claude/guard-hooks/edit-timestamps.json文件重置编辑时间戳。或者编写一个简单的技能/reset-guards来做这件事。修改守卫逻辑高级你可以修改proof-guard.sh使其逻辑不是基于“会话第一次编辑”而是基于“针对当前讨论的文件的编辑”。这需要更复杂的上下文解析但更精准。症状deliverable-guard在会话结束时不断询问已处理过的文件。根因track-deliverable记录了文件创建但deliverable-guard在处理后如文件被移入项目或删除没有更新账本状态。解决方案确保你的处理逻辑中包含了更新账本的操作。例如如果AI决定将/tmp/report.md移动到docs/并提交那么除了执行mv和git add命令外还应该让AI或通过一个自动化脚本从deliverable-ledger.json中移除该文件的记录或将其状态标记为“已处理”。6.3 性能与扩展考量账本文件膨胀长时间、高强度的会话可能会产生大量的验证和搜索记录使JSON文件变得很大。虽然对性能影响通常不大但可能影响可读性。应对可以定期清理或编写一个压缩脚本将旧的、已关闭的会话证据归档。/ship技能是一个天然的清理点可以在写入连续性文件后清空或归档当前会话的账本。多AI代理协作在像原项目那样的多代理生产环境中账本需要共享。简单的做法是使用一个共享存储如网络目录存放.claude/guard-hooks/。但需要小心处理文件锁避免并发写入冲突。更复杂的方案是使用一个轻量级的键值存储或数据库来替代文件账本。自定义守卫no-hallucination的模式是可扩展的。假设你想防止AI在未检查日志的情况下就说“服务运行正常”你可以创建一个log-check-guard。创建log-check-guard.sh触发短语为“running fine”、“healthy”、“no errors”。创建一个对应的追踪器log-check-tracker.sh监听tail -f,grep error,docker logs等命令。守卫检查log-check-ledger.json中是否有近期检查日志的记录。将新钩子添加到settings.json的相应位置。6.4 与现有工作流的融合与CI/CD集成/orient-full可以扩展为读取CI系统的状态如GitHub Actions, GitLab CI。这样每次会话开始时AI都能知道主分支的构建状态、测试覆盖率趋势从而做出更明智的决策。与任务管理工具集成GOALS_FILE和REMINDERS_FILE可以不是简单的Markdown文件而是指向一个脚本该脚本从Jira、Linear、Trello等工具中拉取当前活动的任务和提醒并格式化为AI可读的文本。/ship在结束时也可以调用API来更新任务状态。“宽松模式”开关有时在快速原型或探索阶段严格的守卫可能显得繁琐。你可以设置一个环境变量如GUARD_STRICT_MODE0并在每个守卫脚本的开头检查它。如果为0则守卫只记录警告而不阻塞。通过一个技能/guards relax和/guards strict来切换这个模式。终极心法no-hallucination带来的最大改变与其说是限制了AI不如说是重塑了开发者与AI协作的纪律。它迫使你和AI都养成“先查证后断言”的习惯。最初你可能会觉得有点慢但很快你会发现这种“慢”避免了大量的“返工”和“调试猜谜游戏”。它把潜在的、耗时的沟通成本和错误成本前置为一次快速的、自动化的证据检查。长期来看这是效率的巨大提升。把它看作是对你和AI伙伴共同工作流程的一次必要且高回报的投资。