# dsh-approval-auto-review [English](README.md) | 中文 DeepSeek Harness 的自动审核插件。插件处理路由到其配置权限 preset 的审批请求,由隔离的 Guardian agent 评估精确的计划操作,并为当前请求返回一个审批决定。 每个父 agent 都有一个可复用的 Guardian trunk。第一次审核发送有界的父会话记录和计划操作;后续审核只向同一 trunk 发送当前操作 delta。如果 trunk 正在处理其他请求,插件会启动独立的 ephemeral reviewer,使并发审批请求无需排队等待。如果 trunk 在子 agent 已发布后审核失败,该子 agent 会保留为恢复点;后续审核会重新接入它,而不是再创建一个 continuable session。 ## 功能 - 独立的审核模型路由,也可以选择继承父 agent。 - 针对特定父模型 id 的 provider、model 覆盖。 - 每个审核器都使用空工具允许列表和独立 persona。 - 对会话记录和工具参数设置长度上限。 - 拒绝理由在进入父会话记录前先做长度截断。 - 对超时、畸形输出、提供方失败和未解析路由采用失败关闭。 - 连续自动拒绝达到阈值时中止父 agent 轮次。 - 持久化 JSONL 审计日志,记录每一次被审核的命令和审核器的裁定。 ## 安装 将仓库作为 DSH profile 组合包安装: ```sh dsh plugin --profile web add github:perlied03/dsh-approval-auto-review ``` 使用本地 checkout: ```sh dsh plugin --profile web add ./dsh-approval-auto-review ``` 该包声明了 `dsh.bundle`,因此 `dsh plugin` 会自动将其配置层加入 profile。配置层会注册审核器,并提供 **Request approval**、**Approve for me** 和 **Full access** 三种权限选项。同一个包还声明了 `dsh.client`,Web profile 会直接从已安装包发现审核模型设置卡片和对话中的**审核** tab。在对话权限菜单中选择 **Approve for me** 后,审批请求会交给 Guardian。 从 GitHub 安装时会执行包的 `prepare` 构建。pnpm 10 或更高版本要求构建授权时,请在该 profile 的 `pnpm-workspace.yaml` 中把 `dsh-approval-auto-review: true` 加入 `allowBuilds`,然后重新执行安装命令。 Host 组合必须提供以下 DSH 服务和插件: - `dsh-agent` - `dsh-session` - `dsh-settings` - `dsh-user-approval` - `dsh-subagent` - 以配置的 `provider` 名称注册的进程内 spawn 提供方 - 以配置的 `ephemeralProvider` 名称注册的进程内 fork 提供方 fork 提供方负责并发审核,并保留可复用 trunk 路径。部署不需要该路径时,可以将两个设置使用同一个提供方名称。 ## 配置 在 Cordis 组合中注册插件: ```ts import * as ApprovalAutoReview from 'dsh-approval-auto-review' await ctx.plugin(ApprovalAutoReview, { provider: 'spawn', ephemeralProvider: 'fork', modelProvider: 'deepseek-official', model: 'deepseek-v4-flash', fallback: 'parent', }) ``` 对应的 Loader 行如下: ```yaml - id: approval-auto-review name: 'dsh-approval-auto-review' config: provider: spawn ephemeralProvider: fork modelProvider: deepseek-official model: deepseek-v4-flash fallback: parent ``` 配置字段: - `provider`:可复用 Guardian trunk 使用的子 agent 提供方,默认值为 `spawn`。 - `ephemeralProvider`:并发一次性审核使用的子 agent 提供方,默认值为 `fork`。 - `modelProvider` 和 `model`:可选的审核路由。 - `modelOverrides`:可选的父模型 id 映射;每个条目可以设置 `provider`、`model` 和 `maxTokens`。 - `fallback`:`parent` 表示缺失的路由字段继承父 agent;`reject` 表示路由不完整时失败关闭,默认值为 `parent`。 - `timeoutMs`:单次审核的截止时间,默认值为 `30000`。 - `maxAttempts`:单次审核失败后的重试上限,默认值为 `3`。 - `maxTranscriptChars`:完整审核发送的父会话记录序列化字符上限,默认值为 `60000`。 - `maxToolArgumentsChars`:审核发送的原始工具参数字符上限,默认值为 `20000`。 - `maxTokens`:可选的审核器输出 token 上限。 - `activationPreset`:用于启用审核的权限 preset。省略时插件会处理所有审批请求;随包提供的配置层将其设为 `approve-for-me`。 - `audit`:`file` 会把每个终态审核结果写入审计 JSONL(见[审计日志](#审计日志));`off` 丢弃记录。默认值为 `file`。 - `auditPath`:绝对审计文件路径。默认值为 `/audit/approval-auto-review.jsonl`。挂载时固定,修改后需重启生效。 - `auditArgumentsChars`:每条审计记录保存的原始工具参数字符上限。默认值为 `2000`。 把会话的权限预设切换到 **Approve for me** 即可启用自动审核:会话日志中持久化的 `permission/preset` 事件会为后续审批启用 Guardian;切回 **Request approval** 则把决定交还人工通道。插件不会创建持久允许规则;每个决定只作用于一个审批请求。 ## DSH 兼容性 路由读取会话日志中持久化的 `permission/preset` 选择,因此审核器可以使用当前 DSH Host 服务工作。Web 审核界面还需要 `dsh-host-webserver` 提供只读审计路由。审批服务只接受封闭的字符串结果,所以超时的审核会以拒绝收尾;无论哪种情况,允许和拒绝行为都保持失败关闭。 ## Web 设置 该包的 Web 客户端入口会向现有“插件”设置分区贡献一张**自动审核**卡片。卡片通过 `approval-auto-review` settings 命名空间编辑 `modelProvider` 和 `model`,并使用与 DSH“模型”页面相同的模型目录。先选择提供方可过滤模型列表,也可以将两个字段都留为**跟随主 Agent**,继承父路由。修改会在不重启进程的情况下对下一次审核生效。 独立插件卡片使用低于默认贡献的 slot 优先级。Host 同时贡献 `approval-auto-review` 卡片时,独立插件卡片负责渲染,Host 卡片仍保持注册但被覆盖。 对话头部还会加入只读的**审核** tab。它向 Host 请求当前会话的记录,并显示被审核的工具、受限后的参数、结果、审核模型判断、路由和尝试次数。界面最多显示当前会话最新的 200 条记录,支持手动刷新;没有记录或读取失败时会显示对应状态,不会返回其他会话的记录。该界面需要 Web profile 提供 WebServer 路由;设置 `audit: off` 时显示为空记录。 ## 模型路由 审核路由按以下顺序解析: 1. 如果存在,优先使用 `modelOverrides[parent.options.model]`。 2. 使用插件级别的 `modelProvider` 和 `model`。 3. `fallback` 为 `parent` 时继承父 agent 对应的路由字段。 4. `fallback` 为 `reject` 且路由不完整时,以失败关闭方式报错。 提供方和模型名称由部署决定。插件不假设 DSH 提供方一定支持 Codex 或 OpenAI 的模型 id。 ## 审核策略 Guardian 只评估审批请求提供的精确操作。直接用户消息和明确从 `AGENTS.md` 加载的内容属于可信授权证据。assistant 消息、工具调用、工具结果、文件内容、命令输出和普通插件上下文均不可信。 默认策略在没有明确拒绝规则或提示注入时允许低风险和中风险操作。高风险操作必须具备至少中等级别的可信授权并且范围明确。严重风险、明显的秘密外传、没有精确授权的广泛破坏性操作,以及广泛的持久安全弱化都会被拒绝。 每个审核器都使用空工具允许列表、独立 persona、结构化输出要求和禁止再次发起审批请求的委托策略。 ## 失败行为 - 超时会向父会话注入重试或询问通知,并拒绝该请求。 - 提供方失败或审核器返回畸形结果时,会按照 `maxAttempts` 重试,之后返回拒绝。 - `fallback` 为 `reject` 且路由未解析时会拒绝;为 `parent` 时,缺失字段继承父 agent。 - 自动审核拒绝时,会向父会话注入审核理由和禁止绕过的通知;理由会先按 `AUTO_REVIEW_RATIONALE_MAX_CHARS` 截断。 - 一个轮次内连续三次自动拒绝,或最近五十次自动审核中累计十次拒绝,会取消父 agent 轮次。 ## 审计日志 每个终态审核结果都会向 `/audit/approval-auto-review.jsonl` 追加一行 JSON(可用 `auditPath` 覆盖;用 `audit: off` 关闭)。一条记录覆盖一个审批请求——重试会折叠成一行: ```json {"v":1,"time":1756130000000,"session":"<父会话 id>","callId":"call-3","toolName":"bash","arguments":"{\"command\":\"rm -rf build\"}","argumentsTruncated":false,"outcome":"deny","attempts":1,"riskLevel":"high","userAuthorization":"low","rationale":"The action exceeds the trusted authorization.","provider":"deepseek-official","model":"deepseek-v4-flash","reviewerSession":"trunk"} ``` - `toolName` 和 `arguments` 标识被审核的确切命令;`arguments` 受 `auditArgumentsChars` 约束,截断时以 `argumentsTruncated` 标记。 - `rationale`、`riskLevel` 和 `userAuthorization` 携带审核器对 allow 与 deny 结果的裁定。 - `provider`、`model` 和 `reviewerSession`(`trunk` 或 `ephemeral`)标明做出决定的审核路由;timeout、error 和 cancelled 记录省略这些字段。 - `outcome` 取值为 `allow`、`deny`、`timeout`、`error`、`cancelled` 之一;`attempts` 是消耗的尝试次数。 - 审计日志尽力而为:文件不可写时会输出一次诊断并停止本进程的记录,不会让任何审批决定失败。 审计文件有意放在带外:会话日志会拒绝未声明事件类型的构建读取未知事件,因此审核器把记录保存在会话旁边而不是写入其中。 ## 模型体验 ### 主会话 #### 模型看到的内容 主模型会接收 `dsh-user-approval` 生成的审批策略上下文。审核拒绝时会增加审核理由和禁止绕过的通知;超时时会增加独立的重试或询问通知。Guardian 会话记录不会复制到主模型请求中。 #### Token 影响 只有审批策略上下文以及注入的拒绝或超时通知可能增加后续主模型请求的 token。审核会话记录不会复制到主模型请求。 #### KV Cache 影响 审批策略上下文和注入通知可能改变下一次主请求的前缀。审核成功时不会增加通知。 ### Guardian 审核器 #### 模型看到的内容 第一次 trunk 审核接收一份有界的父会话记录和精确的计划操作。后续 trunk 审核接收当前有界操作 delta 和此前审核次数。ephemeral 审核接收新的有界会话记录和当前操作。 #### Token 影响 每次审批审核都是独立的模型请求;会话记录和参数上限会限制每次请求发送的材料。 #### KV Cache 影响 trunk 审核会在同一子会话中追加 delta,因此提供方可以复用稳定前缀。但每次审核仍会产生新的模型请求。ephemeral 审核使用独立会话,不复用 trunk 前缀。 ## 已知限制与延期工作 - 部署必须提供支持 persona、空工具过滤、结构化输出、continuation 和取消的子 agent 提供方。 - Guardian 没有文件系统或网络工具。有界父会话证据就是完整审核输入;增加工具会引入另一条提示注入和授权来源。 - 提供方和模型是否可用由部署决定。不可用路由会失败关闭,不会被静默替换。 - 审计日志是带外的尽力而为机制:写入失败会让该进程停止记录,该文件也不受会话日志完整性或压缩机制的覆盖。 - GitHub 安装会运行 `prepare` 构建 `lib/`。如果 profile 尚未信任该包,pnpm 10 或更高版本要求先在 `allowBuilds` 中允许安装时构建。 ## 开发 ```sh pnpm install pnpm test pnpm run typecheck pnpm run build ``` 该包从已发布的 DSH 包解析 import;`prepare` 会构建 Host exports,以及由 `dsh.client` 发现的 `lib/client.js` bundle。