dsh-auto-review
English | 简体中文

DeepSeek Harness 的 LLM 自动审查审批应答器:当会话的审批策略为 'auto' 时,超出 workspace-write 的沙箱升级请求(sandbox_permissions: "danger-full-access" + 理由)无需人工提示即可裁决 —— 只有当审查模型不确定时才问人,所有错误路径一律失败关闭(fail-closed)。
两层裁决,按顺序:
1. 确定性过滤器 —— hardline(绝对拒绝)+ deny/allow 正则规则,作用于归一化后的命令(~/$HOME 展开、注释剥离、空白折叠、macOS 私有路径折叠)。命中 hardline 或 deny 立即拒绝;命中 allow 立即放行;两者都不调用 LLM。确定性拒绝是最终裁决 —— 运营者策略永不被上诉推翻。 2. 清洁上下文 LLM 安全审查 —— 灰色地带交给一个小型审查模型:固定常量系统提示词、temperature: 0、单词裁决(ALLOW / DENY / UNSURE)、紧凑的输出上限。user 消息只携带工具名、理由和 XML 包裹的命令 —— 绝不携带对话内容。
上诉模式(context: 'appeal-user-prompts',默认):LLM 给出的 DENY 会以会话的真实用户提示词作为意图证据重审一次 —— 提示词通过确定性方式提取(绝不经 LLM 摘要),只取 source kind 恰好为 'user' 的 user/message 事件。上诉只能放宽拒绝、绝不能收紧放行:它用于减少误报,不是检测能力升级。
应答器以 { prepend: true } 注册在 approval/request 上,先于任何人工/机器通道运行;当有效策略不是 'auto' 或请求不携带动作时,用 next() 委托给后续通道。审查器是抵御"诚实但犯错"模型的纵深防御,绝不是沙箱放宽机制:在授权落地前,workspace-write 始终是边界。可选的连续拒绝熔断器(denialBreakerThreshold)在产生更多 LLM 开销前短路重试循环。
⚠ 核心依赖警告:需要打过补丁的 harness 核心
本插件无法在原版上游 deepseek-harness 上运行。它依赖三个补丁核心能力,已作为两个 git patch 随 [core-patches/](core-patches/) 发布(基于上游提交 47f943859b,即 PR #2519 合并提交),附 rebase 指南:
0001-approval-auto-policy-and-escalation-action.patch——'auto'审批策略、ApprovalRequest.action、ApprovalService.effectivePolicyFor,以及携带升级动作的 tool/sandbox/permission-presets 接线。0002-llm-auto-review-request-purpose.patch——'auto-review'LLM 请求用途。
同步上游后用 git am(或 git apply)按顺序应用;若与上游冲突,手工解决后重新生成 —— 详见 [core-patches/README.md](core-patches/README.md)。
在 vanilla 上游上插件刻意保持惰性: 策略闸门永远不会解析为 'auto',所有升级请求都通过 next() 惰性委托给正常的人工应答器。不会崩溃、不会自动裁决 —— 但在补丁核心就位前你得不到自动审查。
安装
前置条件:打过补丁的 harness 构建(见上);profile 的权限预设须包含 auto-review 预设(sandbox: workspace-write + approval: auto)—— patch 0001 已将其加入 harness 的 permission-presets 包。
从 GitHub 安装(通过包的 prepare 脚本在安装时构建;pnpm 会要求你允许一次构建):
dsh plugin --profile web add github:accpowered/dsh-auto-review如果 pnpm 打印 allowBuilds 提示,把打印的键加入 profile 目录 pnpm-workspace.yaml 的 allowBuilds 下并重跑 add —— 这等于授予安装期执行权限,只允许你信任的来源(建议固定 commit:github:accpowered/dsh-auto-review#<sha>)。
本地检出安装:
dsh plugin --profile web add ./dsh-auto-review重启 dsh web(或对应 profile)。bundle patch([cordis.patch.yml](cordis.patch.yml))插入一个 host 行,带默认审查路由(deepseek-official / deepseek-v4-flash)。要换审查模型,在你的 profile 的 cordis.patch.yml 中重写该行 —— provider 和 model 为必填,且 patch 会替换整行配置:
- id: auto-review
name: dsh-auto-review
config:
provider: my-provider # 任意已注册的 LLM 路由
model: my-small-model配置项
全部可调项(composition = cordis.patch.yml 行配置;user = 通过 auto-review 设置命名空间实时覆盖):
| 键 | 默认值 | 组合层 | 用户可覆盖 | 作用 |
|---|---|---|---|---|
provider | —(必填) | ✓ | ✓ | 审查路由(已注册的 provider) |
model | —(必填) | ✓ | ✓ | 该路由上的审查模型 id |
hardline | 内置列表 | ✓ | — | 绝对拒绝正则;策略为 auto 期间永不被绕过 |
deny | 内置列表 | ✓ | ✓ | 可配置的拒绝正则 |
allow | 内置列表 | ✓ | ✓ | 可配置的放行正则(仅限保守、无副作用命令) |
maxTokens | 512 | ✓ | — | 审查输出 token 上限(单词裁决 + 余量) |
timeoutMs | 15000 | ✓ | — | 审查端到端时限(毫秒) |
onError | deny | ✓ | ✓ | 审查失败回退:deny(失败关闭)或 ask(问人) |
onUnsure | ask | ✓ | ✓ | UNSURE 裁决回退:ask(问人)或 deny |
denialBreakerThreshold | 0(关) | ✓ | ✓ | 连续拒绝熔断阈值 |
context | appeal-user-prompts | ✓ | ✓ | appeal-user-prompts 或 minimal(仅命令,v1 行为) |
appealMaxPrompts | 0(不限) | ✓ | ✓ | 上诉预算:附带的最新用户提示词条数(首条豁免) |
appealMaxChars | 0(不限) | ✓ | ✓ | 上诉预算:附带的用户提示词总字符数 |
hardline、maxTokens、timeoutMs 刻意保持仅组合层可配。内置过滤器默认值见 src/index.ts(DEFAULT_HARDLINE_PATTERNS / DEFAULT_DENY_PATTERNS / DEFAULT_ALLOW_PATTERNS)。
用户层实时覆盖
用户可调键位于 auto-review 设置命名空间(通过 installSettingsSection 注册;命名空间名保持 auto-review,已有用户设置文档继续生效)。组合条目是基础层;已提交的用户层变更在下一次裁决时即刻重新解析并重编译规则 —— 无需重启。携带非法正则的写入会在设置接缝处被拒绝,坏规则永远到不了编译后的过滤器。
卸载
dsh plugin --profile web remove dsh-auto-review应答器和设置小节随插件 fiber 一并卸载。会话日志上已有的 auto-review/decision 事件(仅日志)不受影响,auto-review 预设下的会话回退到人工应答器。
开发
pnpm install
pnpm build # tsc 声明(lib/types)+ tsdown(lib/index.js)
pnpm test # vitest:过滤器/裁决/上诉流程、设置生命周期(本地审批 stub)目录:src/index.ts(整个插件 —— 应答器、配置 schema、设置小节、导出的纯函数)、tests/auto-review.spec.ts + tests/stubs.ts(stub 复刻了打过补丁的 ApprovalService 的派发语义;npm rc.1 包早于 'auto' 策略)、core-patches/(两个必需的核心 patch + rebase 指南)。
许可证
MIT