# dsh-approval-review bundle layer. # # A YAML array of row verbs; `insert` adds plugin rows to the composed config. # A row's `id` is unique within the layer stack, and `name` resolves the plugin # module through the installed package (`package.json#main`). # # Layer semantics: an id-targeted override REPLACES this whole config row, so a # deployment that overrides any key must restate every key it still wants. # Dropping `reviewTools` returns the tool table to its schema default, and # dropping `defaultPolicy` returns unlisted tools to `human` — i.e. back to the # ordinary approval prompt. - insert: - id: approval-review name: dsh-approval-review config: # Master switch. `false` mounts the plugin but claims nothing; the # per-session `/approval-review on|off` switch is the runtime lever. enabled: true # Session-start default for that switch. enabledByDefault: true # Tool names routed to the reviewer model. Everything else falls through # to `defaultPolicy`, whose default delegates to the human answerer. # `edit` is deliberately absent: in-place modification of an existing # file is the highest-consequence routine action, so it keeps the human # prompt until a deployment decides otherwise. reviewTools: - bash - pwsh - write defaultPolicy: human # Ordered regex rules, evaluated before the tool table. `field` selects # what the pattern is matched against: `reason` (default), `toolName`, or # `arguments`. rules: [] # Reviewer model, prompt, and size limits. `provider`/`model` unset means # the reviewer inherits the calling agent's own route. reviewer: timeoutMs: 60000 maxTokens: 1024 temperature: 0 argumentMaxChars: 4000 argumentsBudgetChars: 16000 # policyText: | # replaces the shipping ruling policy # # guidance: # Transcript evidence handed to the reviewer; `turns: 0` sends none. context: turns: 2 maxChars: 6000 includeAssistant: true includeToolActivity: true # Risk gate: an allow verdict above this grade is not auto-allowed. maxAutoAllowRisk: medium onRiskExceeded: delegate # Reviewer said it could not decide. onUncertain: delegate # Reviewer crashed, timed out, or answered off-schema. `rejected` is the # fail-closed stance; `delegate` hands the request to the human chain. onReviewerFailure: rejected # Per-turn reviewer budget, so a loop cannot bill unlimited reviews. budget: maxReviewsPerTurn: 20 onExhausted: delegate # Rejection circuit breaker, matching Codex's per-turn denial breaker: # stop escalating after repeated refusals instead of looping. circuitBreaker: consecutiveDenials: 3 windowDenials: 10 windowSize: 50 action: delegate # One-shot `/approval-review approve [n]` authorization. override: ttlMs: 300000 maxPending: 10 reasonMaxChars: 2000 # Append the reviewer's rationale to the refused tool result the model # reads. This is also what makes the card's rationale durable, so turning # it off costs the model its explanation AND the card its reason line. feedReasonToModel: true # Append the ALLOW verdict to the accepted tool result. An approval # outcome is a closed vocabulary, so the tool result is the only channel # this plugin can write durably without inventing a session event type; # without it an allowed row shows THAT an action ran but never WHY. The # cost is one short marker block in the model's context per auto-allowed # call; turning it off empties the "rationale" line of allowed rows. recordAllowedVerdicts: true language: en # --- "Approve for me" as a PEER access-mode option ------------------------- # # The access-mode menu is data-driven from this table, so a fourth entry shows up # beside 仅可查看 / 工作区内修改 / 完全权限 with no client change. # # Why this works even though the bundle is identical to `workspace-write`: # `PermissionPresetService.derive()` checks the RECORDED selection first and # returns it when its knobs still match, so the remembered preset key wins over # the first table match. Selecting "Approve for me" therefore stays selected. # # An id-targeted override REPLACES the whole row, so the shipped three entries # must be restated here verbatim. - id: permission config: presets: read-only: sandbox: read-only approval: ask name: 仅可查看 description: 只能读取,任何修改都需要批准。 workspace-write: sandbox: workspace-write approval: ask name: 工作区内修改 description: 可在工作区与临时目录内修改;更宽的操作需要批准。 danger-full-access: sandbox: danger-full-access approval: never name: 完全权限 description: 不受限的文件与网络访问,不再弹审批。 # The fourth peer option. Its knobs deliberately match `workspace-write`: # the difference is WHO answers the approval — this plugin's reviewer # instead of a human prompt. `dsh-approval-review` only claims requests # while this preset is the active one. approve-for-me: sandbox: workspace-write approval: ask name: 替我审批 description: 与"工作区内修改"相同的边界,但需要批准的动作先交给复核模型,只有危险或不确定的才转人工。