AI 为何无法绕过 Claude Code Harness 的护栏?执行前裁决机制设计哲学
【免费下载链接】claude-code-harnessClaude Code Dedicated Development Harness - Achieving High-Quality Development Through an Autonomous Plan→Work→Review Cycle项目地址: https://gitcode.com/GitHub_Trending/cl/claude-code-harness
Claude Code Harness 是一个面向 Claude Code、Codex、Cursor、Grok 的自主开发护栏框架,核心是用「计划 → 执行 → 审查」的可重复闭环来保证交付质量。它真正让人安心的地方不在模型有多聪明,而在于每一次工具调用在运行之前都会先被一个 Go 引擎裁决一遍——而不是等代码写完、文件 diff 出来之后才回头检查。这就是本文要拆解的「执行前裁决机制」设计哲学:AI 不是被关进笼子,而是被装上了一套有硬地板、有可配置护栏、有审计留痕的安全底盘。
🧭 先看清楚:Claude Code Harness 到底在解决什么问题
AI 自主编码最大的风险不是"写不出代码",而是它会在无人盯着的时候,悄悄地做一些危险动作:把计划写进聊天记录然后消失、为了赶进度把测试做成可选项、在代码已经合并之后才做审查、把本该在隔离工作区里的删除操作扩散到整个项目。
Harness 的思路很直白:先写规格,只实现已批准的切片,独立审查,再打包证据。下面这张图是它官方的运行循环,从 Spec(规格)到 Plan(计划)、Work(执行)、Review(审查)、Release(发布),每一步都留好给下一步用的材料。
但循环本身解决的是"流程",真正让护栏"绕不过去"的,是下面这套裁决引擎。
🛡️ 为什么"执行前裁决"是绕不开的关键
大多数 AI 编码工具的审查都发生在事后:代码已经跑了、网络请求已经发了、文件已经删了,然后才拿着一份文件 diff 来"评审"。Harness 认为这条路走不通,原文里写得很直接:
一份文件 diff看不到一次网络发送,也看不到一次删除。
于是它把裁决时机提前到了工具调用真正执行之前:AI 每发起一次Bash、Write、Read等操作,都会先经过一个纯 Go 引擎的裁决,返回三种结果之一——
- Deny(拒绝):直接拦下,不执行;
- Ask(确认):暂停,等人类点头;
- Warn(警告):放行,但在上下文里留下一条提醒。
这个裁决入口在 go/internal/guardrail/pre_tool.go 的EvaluatePreTool,执行顺序是先过硬地板、再过可配置护栏,顺序本身就是安全设计的一部分。
⚙️ 双层护栏:一张不可覆盖的"硬地板" + 一张可调的护栏网
Harness 把安全拆成两层,且故意让两层强度不同。这不是冗余,而是把"绝对不能碰的红线"和"项目可以按自己情况调的偏好"分开管理。
第一层:运行时硬地板(Runtime Action Hard Floor)——不可覆盖
这一层实现于 go/internal/runtimefloor/runtimefloor.go,它专门拦截 Bash 命令,覆盖 5 个类别,且没有任何关闭开关——不是靠配置项、环境变量或权限模式能关掉的那种:
| 类别 | 拦截什么 | 为什么是红线 |
|---|---|---|
| 资金/计费 | stripe、paypal、aws ce、gcloud billing | 涉及真实扣费,绝不该由 AI 自主发起 |
| 对外网络 | 非白名单主机的curl/wget/nc/scp | 防数据外泄,diff 根本看不到 |
| 读取密钥 | cat .env、~/.ssh、*.pem、credentials | 凭据不该被 AI 随手读走 |
| 生产发布 | npm publish、kubectl apply、gh release | 影响线上,必须人来按 |
| 越区破坏 | 工作区之外的rm类破坏性命令 | 防止删除操作扩散出隔离区 |
关键细节:这一层跑在一条隔离的代码路径上,没有 disable 开关,所以一次自主运行没法"说服"它放行。即便项目配置文件损坏、解析失败,它也会默认拒绝(fail-safe),而不是默认放行。
第二层:可配置护栏 R01–R15——你能调的那张网
这一层实现于 go/internal/policy/rules.go,是一条按顺序匹配、首个命中即返回的声明式规则表。每条规则都有一个Rxx编号和明确的裁决结果,部分可以按项目配置调整:
| 编号 | 拦截什么 | 结果 |
|---|---|---|
| R01 | sudo | 拒绝 |
| R02 / R03 | 写保护路径 / 用 Bash 写保护路径 | 拒绝或确认 |
| R04 | 写项目根之外 | 确认 |
| R05 | 危险删除命令 | 确认 |
| R06 | git push --force | 拒绝(工作模式下也拦) |
| R10 | --no-verify/--no-gpg-sign | 拒绝(不许绕过钩子) |
| R11 | 保护分支reset --hard | 拒绝 |
| R12 | 直接推保护分支 | 拒绝 / 确认(可配置) |
| R15 | 暂存密钥文件 | 拒绝 |
这套设计的哲学是:红线交给硬地板去死守,偏好交给护栏去调,两件事互不干扰,谁也别想替谁松口。
这里有个容易被忽略的"隐藏细节":整个裁决引擎是Go 原生实现的,不再依赖 Node.js。好处不只是性能——而是让裁决逻辑变成一个可审计、可测试、可复现的单一可信源,而不是散落在各处 shell 脚本里、容易被环境差异悄悄削弱的一段段代码。
📋 计划时批量预批准:不打断执行流,也不开后门
如果 AI 每遇到一个风险操作就停下来问一次,自主执行会被打断得支离破碎。Harness 的解法很巧妙:把确认从"执行时"挪到"计划时",一次性问清。
实现见 go/internal/guardrail/plan_preapproval.go。它会在计划阶段收集这次计划需要的高风险操作,一次性让你批。但这份批准不是无限通行证,它自带三道锁:
- 有效期(ExpiresAt):过期自动失效;
- 任务作用域(Scope):只对当前 phase + task 生效,换个任务就作废;
- 使用次数上限(MaxUses):默认最多 10 次,用满即止。
一次批准,永远不会变成一个永久后门。
而且预批准只能压掉"确认"(Ask)这一档,永远压不掉显式拒绝(Deny)分支,也压不掉跑在它前面的运行时硬地板。换句话说,批准给你的是"少问几次"的便利,而不是"随便放行"的权力。
📊 每一次拦截都被留痕:你数得出到底挡了什么
护栏拦了一次,你凭什么知道?Harness 把所有裁决结果都写进一份 JSONL 审计日志,见 go/internal/auditlog/auditlog.go。它记录规则 ID、类别、裁决结果,但你几乎不用担心日志本身泄露内容:
- 命令文本从不落盘,只存一个 SHA256 哈希和长度;
- 对"读密钥"和"资金/计费"这两类,连哈希都不写;
- 日志写入用文件锁保护,失败会被静默忽略——可观测性永远不会反过来改变护栏的裁决。
这意味着你可以直接"数一数"到底有多少次被拦、分别踩了哪条线,而不是靠猜。
🧠 设计哲学:让 AI 可靠的,不是模型而是"边界"
Harness 有一句点题的话:
它并不让模型变聪明。它固定的是流程和模型周围的那道边界——所以模型再怎么换,它都照常工作。
这正是执行前裁决机制的底层哲学:AI 的能力会变、会漂移,但边界是你可以用代码钉死的。围绕这个目标,源码里还藏着几条很"较真"的设计,都源于真实的对抗性复测(源码注释里明确记录了 2026-08-11 的对抗重验证):
- 防符号链接逃逸:判定文件是否在允许目录内时,会同时做"文本路径"和"解析软链后的物理路径"两道检查——否则攻击者可以在状态目录里埋一个指向别处的软链,把"允许写状态目录"变成"任意写文件"。
- 防路径穿越:
/.claude/state/../../src/x.ts这类..穿越会在 Clean 之后被拒绝。 - 项目根解析不认
.claude:只认.harness/.git,且向上查找时绝不会越过用户主目录——避免一个散落子目录里的.git把整个 home 变成rm -rf的放行区。
一句话:它假设 AI 会想尽办法绕过,然后用代码把每一条可能的缝都先焊死,再让对抗测试来证明"确实焊死了"。
🚀 快速上手:30 秒装好护栏
护栏的价值要在"真的跑起来"时才体现。按 README.md 的路径,安装只有三步:
claude /plugin marketplace add Chachamaru127/claude-code-harness /plugin install claude-code-harness@claude-code-harness-marketplace然后跑一次/harness-setup初始化,再丢给它一件小事试试:
/harness-plan 改进 README 的引导流程它会帮你起草spec.md和Plans.md。记住你的角色——不是去写计划,而是在它继续执行之前去批准或纠正它。从这一刻起,后面每一次写文件、发命令,都会先过一遍上面那套硬地板 + 护栏的裁决。
✅ 小结:AI 绕不过护栏,靠的不是运气
回到标题的问题——AI 为何无法绕过 Claude Code Harness 的护栏?答案是三层机制叠出来的:
- 时机提前:裁决发生在工具调用执行之前,而不是事后看 diff;
- 双层分离:不可覆盖的运行硬地板死守 5 类红线,可配置的R01–R15 护栏管理项目偏好,谁也不能替谁松口;
- 便利有界:计划时批量预批准减少打断,但每份批准都带有效期、任务作用域和使用上限,永远不会变成永久后门;
- 全程留痕:每一次拦截都进审计日志,你能数得出到底挡了什么,且日志本身不泄露命令内容。
它没有试图让 AI 变强,而是把"边界"这件事用 Go 代码钉死——这才是执行前裁决机制真正的哲学:当模型会漂移时,让不漂移的那部分去兜底。
【免费下载链接】claude-code-harnessClaude Code Dedicated Development Harness - Achieving High-Quality Development Through an Autonomous Plan→Work→Review Cycle项目地址: https://gitcode.com/GitHub_Trending/cl/claude-code-harness
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考