☰
Stop That Shit 架构拆解:6 个宿主适配器如何共享同一个 ControlEvent v2 决策核心
2026/10/4 3:33:13 网站建设 项目流程

Stop That Shit 架构拆解:6 个宿主适配器如何共享同一个 ControlEvent v2 决策核心

【免费下载链接】stop-that-shitStop That Shit(别再造史了)|面向 Codex/GPT 场景的多平台 Hook + Skill Guard:拦截 AI coding agent 无需求的哈希、校验和与任务范围膨胀。 A multi-platform Hook + Skill Guard for AI coding agents in Codex/GPT workflows: stop unrequested hashes, checksums, and task-scope creep.项目地址: https://gitcode.com/gh_mirrors/st/stop-that-shit

Stop That Shit(别再造史了)是一款面向 Codex/GPT 等 AI coding agent 的多平台 Hook + Skill Guard:拦截没有需求的哈希校验和、多余防御和任务范围膨胀。它的架构很克制——6 个宿主适配器,只干翻译这一件事;所有"要不要拦"的判断,都交给同一个宿主无关的决策核心。本文带你快速看懂这套"一个大脑、多张面孔"的设计。

🧭 问题:6 种宿主事件,6 套方言

Stop That Shit 目前支持 6 个宿主:Codex、Claude Code、OpenCode、Hermes Agent CLI、Pi、Oh My Pi。麻烦在于,每个宿主的钩子事件名、字段结构、拦截时机都不一样:

宿主原生事件举例对应通用事件
CodexPreToolUse/UserPromptSubmitaction.before/prompt.submit
Claude CodePreToolUse/SubagentStartaction.before/subagent.start
Hermespre_tool_call/pre_llm_callaction.before/prompt.submit
Pitool_call/inputaction.before/prompt.submit

如果在每个宿主里各写一套判断逻辑,规则会慢慢"漂移"——A 宿主拦哈希,B 宿主忘了。Stop That Shit 的解法是把判断和翻译彻底拆开:

适配器只负责把宿主的"方言"翻译成统一事件;决策核心只认统一事件,完全不关心它来自哪个宿主。

📡 ControlEvent v2:6 个适配器的共同语言

翻译的产物就是ControlEvent v2,一个字段非常小的 JSON 事件。它只有 7 种事件类型(定义在 src/control-protocol.cjs):

  • session.start/session.end—— 会话起止
  • prompt.submit—— 用户提交提示词(任务指令从这里进入契约)
  • action.before/action.after—— 工具调用前后,拦截只发生在 before
  • subagent.start/subagent.stop—— 子代理生命周期

一个action.before事件长这样(节选自 HOST-ADAPTER-CONTRACT.md):

{ "protocolVersion": 2, "lifecycleVersion": 2, "kind": "action.before", "sessionId": "opaque", "action": { "name": "Edit", "mutability": "write", "affectedPaths": ["src/config.cjs"], "hashIntent": false } }

其中最关键的字段是mutability(可变更性),只有 5 个取值:read、write、delegate(派生子代理)、control(控制类操作)、unknown。适配器要做的工作,就是把宿主五花八门的工具调用归类到这 5 个桶里。

protocolVersion和lifecycleVersion两个版本号则是一道"门禁":src/controller.cjs 里,只有同时声明了两个版本的适配器,其生命周期事实才允许修改账本;老适配器借用新协议号却保留旧行为时,会自动降级到兼容路径,而不是把错误状态写进会话。

🧠 同一个大脑:handleControlEvent 如何消化所有事件

所有适配器最终都调用同一个入口——src/controller.cjs 的handleControlEvent。它按事件类型分派:

事件核心动作
prompt.submit解析任务指令(如review -- 只审查不修改),更新当前契约
action.before调用decide()做拦截判断,必要时原子地预留子代理配额
action.after根据完成事实释放或保留配额
其余生命周期事件更新子代理账本,回注契约上下文

真正的判断逻辑在 src/decision.cjs,它与宿主完全无关,只做"基于可观察事实的硬决策":

  1. 非修改模式下发生了写操作;
  2. 写入超出files=明确划定的文件范围;
  3. 未授权就添加依赖;
  4. 派生子代理超过agents=N上限;
  5. 高置信度的哈希/校验和行为但没给hash=allow。

决策还分三个档位(src/controller.cjs):

  • OFF:不检查、不记录;
  • OBSERVING(观察):检查并记录,但永不拒绝;
  • ARMED(武装):显式任务契约生效,可以返回 permission deny。

对应四种 SHIT 家族:I(Intent 意图越界)、H(Hash 无用防御)、S(Scope 范围膨胀)、T(Thrash 任务打转)——这正是 src/controller.cjs 里FAMILY_NAMES的由来。

🧩 6 个适配器各自薄成什么样

每个适配器就是"事件映射表 + 工具分类器 + 响应渲染",源码统一放在 src/adapters/ 目录:

适配器事件翻译工具分类
Codexcodex-hooks.cjscodex-tool-classifier.cjs
Claude Codeclaude-hooks.cjsclaude-tool-classifier.cjs
OpenCodeopencode-hooks.cjsopencode-tool-classifier.cjs
Hermeshermes-hooks.cjshermes-tool-classifier.cjs
Pipi-hooks.cjspi-tool-classifier.cjs
Oh My Piomp-hooks.cjsomp-tool-classifier.cjs

以 Codex 为例,codex-hooks.cjs 里就是一张 5 行的映射表:SessionStart → session.start、PreToolUse → action.before……然后构造带protocolVersion: 2, lifecycleVersion: 2的事件对象,丢给handleControlEvent。Claude 和 Hermes 的适配器结构几乎一模一样——换宿主 = 加一个映射表,而不是重写一套规则。

各宿主的包级入口也保持"薄壳"风格:opencode/stop-that-shit.mjs、pi/stop-that-shit.ts、omp/stop-that-shit.ts,各自只负责把宿主回调接到共享控制器上。

⚖️ 边界:适配器是护栏,不是沙箱

架构上有一条值得记住的边界(HOST-ADAPTER-CONTRACT.md):

  • 宿主负责执行、文件系统隔离和权限提示;
  • STS只负责用户的任务约束(文件范围、哈希/依赖授权、子代理预算);
  • 适配器负责工具身份和事件翻译,不靠名字前缀猜测工具身份。

同时,观察到的"Guard 响应"与"宿主实际效果"被刻意分开:审计记录里hostEffect永远是unobserved,因为 deny 响应并不证明宿主一定阻止了执行。所有检查(即使放行)都会写入 src/runtime-audit.cjs 的元数据审计,让统计数字有个真实的分母。

✅ 这套架构给普通用户带来的好处

  1. 行为一致:在 Claude Code 里被拦的哈希,在 Codex 里同样会被拦,因为判断只有一份;
  2. 新增宿主成本低:照着 HOST-ADAPTER-CONTRACT.md 的 4 项条件(稳定会话 ID、提示词入口、可拒绝的 before 事件、足够分类的工具信息)实现一个薄适配器即可;
  3. 可审计:$stop-that-shit status/runtime命令随时能查本会话的检查次数和拒绝次数;
  4. 失败安全:状态文件损坏时进入只读恢复而不是崩溃,审计写失败也不改变控制决策。

📚 延伸阅读

  • 架构总览:ARCHITECTURE.md
  • 适配器契约与事件映射细节:HOST-ADAPTER-CONTRACT.md
  • 契约解析与指令语法:src/contracts.cjs
  • 子代理配额账本:src/delegation-state.cjs
  • 会话状态存储:src/state.cjs
  • 规则本体(Stop Ladder):skills/stop-that-shit/SKILL.md
  • 18 个 Bad/Good 判定用例:cases/README_CN.md

一句话总结:6 个适配器负责"听懂",同一个 ControlEvent v2 决策核心负责"做对"——这就是 Stop That Shit 能在多宿主间保持判断一致的架构秘密。

【免费下载链接】stop-that-shitStop That Shit(别再造史了)|面向 Codex/GPT 场景的多平台 Hook + Skill Guard:拦截 AI coding agent 无需求的哈希、校验和与任务范围膨胀。 A multi-platform Hook + Skill Guard for AI coding agents in Codex/GPT workflows: stop unrequested hashes, checksums, and task-scope creep.项目地址: https://gitcode.com/gh_mirrors/st/stop-that-shit

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询