Skip to main content

dsh-auto-review

58Stars1Forks1Issues0Watchers

Insert a second read-only AI model review request in the DSH approval step, requiring dangerous tools to undergo independent judgment before execution with rejection as default and full audit logging.

Evidence5/5methodologySourceInstallMaintenanceDSH versionSecurity scan
Machine-auditedInstall commandRepo verifieddsh-plugin topicLicenseREADMEAI wiki
Language
TypeScript
License
Apache-2.0
Branch
main
ai-safetyapprovalauto-reviewcordisdeepseekdeepseek-harnessdshdsh-plugin

Install

cmdweb profile
$ dsh plugin --profile web add dsh-auto-review

Run the command above in your terminal to install this plugin via the dsh CLI. You can switch Profile in the top-right corner. New to dsh? Read the beginner tutorial

Install via your agent

Install the DeepSeek Harness plugin PerryLink/dsh-auto-review for me: review the repository at https://github.com/PerryLink/dsh-auto-review first, then run the install command and verify the plugin loads successfully.

Paste this instruction to the DSH Web GUI assistant — it will install and verify for you.

One-line Positioning

Attach a second model to DeepSeek Harness's approval chain, letting sandbox-external tool calls first be read by a read-only sub-agent that returns allow/deny; failures default to deny, with full session logging. Comes with risk level policies, deny circuit breaker, and a web visual panel.

Core Capabilities

  • Second Model Approval: Register a hook on the approval/request answerer chain; tools matching the ai policy are routed to a read-only sub-agent for judgment, all other requests go through next() to the original human approval chain.
  • Structured Verdict: The review sub-agent returns { decision, reason, riskLevel } via structured output; only read/glob/grep这三个只读工具 are available, so it cannot actually execute the action under review.
  • Fail-Open is Not an Option: Review timeout, crash, sub-agent unavailable, or malformed verdict all trigger fallbackPolicy (default rejected)—nothing gets silently passed through; can be changed to delegate (to human) or allow-once (one-time allow, explicitly marked as dangerous in docs).
  • Risk Level + Circuit Breaker: When the verdict's riskLevel exceeds maxAutoAllow, you can configure delegate or deny; consecutive denials or sliding-window denials trigger a circuit breaker with one of three actions: delegate / reject / abort-turn.
  • Deny Reason Reflow to Model: Denied tool results get injected with [auto-review] / [auto-review-fallback] / [auto-review-never] markers plus the denial reason and bypass-prevention hints, so the model can see why it was denied and why it can't try a different approach.
  • Full Audit + Web Panel: Five event types—autoReview/state, autoReview/verdict, autoReview/rejection, autoReview/circuit, autoReview/override—are written to session logs; the web profile adds an AI Review button in the session header, showing toggle, budget, cumulative stats, recent verdicts, and one-time approvals.

Technical Implementation

  • Language: TypeScript (ESM, type: module)
  • Key Dependencies: @deepseek-ai/cordis (plugin host framework), @deepseek-ai/schemastery (config schema + defaults), @deepseek-ai/dsh-session + @deepseek-ai/dsh-session-projection (session log + web panel data channel), @deepseek-ai/dsh-subagent (review sub-agent orchestration), zod (projection wire schema validation)
  • Architecture Pattern: Uses Cordis function plugin contract (name + inject + apply), registers side effects via ctx.on('approval/request', ...), ctx.on('tools/post-execute', ...), ctx.commands.register(...); mounts the autoReview projection unit to the web panel via ctx.inject(['sessionProjections']) when supported by host
  • Entry Files: src/index.ts (plugin export), runtime.ts (approval answerer + commands), review.ts (review sub-agent orchestration), config.ts (Schemastery schema + resolveConfig)

Use Cases

You want to run DSH in an unattended environment but don't trust the main model to unilaterally perform side-effecting operations like "write file" or "run command"; after installing this plugin, every sandbox-external action the main model wants to take is first read by a second model, which provides a verdict and reasoning. Failed fallbacks conservatively deny, and the entire process is auditable and replayable from session logs.

Prerequisites and Compatibility

DependencyMin VersionNotes
DeepSeek Harness0.1.0-rc.7All dsh-* peerDependencies are precisely locked to 0.1.0-rc.7, and dshWorkshop.compatibility.dshVersions only lists this version
Node.js^22.19.0 || >=24.0.0Declared in package.json#engines.node
Cordis^4.0.1peerDependencies
Schemastery^3.18.0peerDependencies
PlatformCross-platformHost side is pure JS with no native module dependencies; Web review panel only registers under web profile
Native ModulesNoneNo os/cpu restrictions, no node-gyp/node-pty or similar dependencies

Installation

dsh plugin --profile web add github:PerryLink/dsh-auto-review

Configuration Options

ConfigTypeDescriptionDefault
enableByDefaultbooleanWhether new sessions enable auto-review by default; `/auto-review onoff` writes override events
toolsPolicy.defaultai | human | neverPolicy for tools not listed in the tool tablehuman (to human)
toolsPolicy.overridesobjectTool → policy mapping, e.g., { bash: ai, write: ai }{}
riskRulesarrayRegex matching request reason/toolName/parameters + policy (evaluated before tool table)[]
reviewerProviderstringSubagent provider for the review sub-agentfork (in-process fork)
reviewerModelstringModel ID for review; inherits current session model if not specifiedInherit
reviewerTimeoutMsnumberTimeout in ms for review sub-agent; timeout triggers fallbackPolicy60000
reviewerToolsstring[]Tools the review sub-agent is allowed to use (whitelist, must be non-empty)["read","glob","grep"]
fallbackPolicyrejected | delegate | allow-onceWhat to do on review failure (timeout/crash/structure error)rejected (conservative deny)
maxReviewsPerTurnnumberMax real AI verdicts per turn; exceeding routes to human10
maxFailuresPerTurnnumberMax review failures per turn; exceeding routes to human10
reasonMaxCharsnumberMax chars for review reason / request reason / parameter preview2000
reviewerGuidancestringOptional guidance appended to review prompt (advisory, not hard constraint)None
reviewerPolicyTextstringMarkdown policy template injected into review prompt like CodexNone (see fixtures/config/policy-template.md)
denyGuidancestringBypass-prevention hint appended each time a denial reason is injectedDefault English + default Chinese
contextBudget.turnsnumberHow many turns of session content to show the review sub-agent; 0 = off0
contextBudget.maxCharsnumberMax total chars for context chunk4000
riskPolicy.maxAutoAllowlow | medium | highMax allowed riskLevel for verdicts; exceeding triggers delegate or denyhigh
riskPolicy.onHighRiskdelegate | denyWhat to do when exceeding maxAutoAllowdelegate
circuitBreaker.consecutiveDeniesnumberConsecutive denials to trigger circuit break3
circuitBreaker.windowDeniesnumberDenials in sliding window to trigger circuit break6
circuitBreaker.windowSizenumberSliding window size (by last N verdicts)10
circuitBreaker.actiondelegate | reject | abort-turnHow to handle subsequent requests in the same turn after circuit breakdelegate
overrideTtlMsnumberValidity in ms for /auto-review approve one-time authorization300000 (5 minutes)
languageen | zhOutput language for /auto-review commandsen
allowUnmarkedAuditbooleanWhether to still write audit events when host doesn't recognize ignorable tags (dangerous: may prevent stricter harnesses from recovering sessions)false

FAQ

Q: Which tools are automatically reviewed by default?

A: Only bash and write are reviewed; other tools go to human approval. edit (in-place modification) was intentionally left out of the default AI review list—if you want in-place modifications to also go through auto-review, just add edit: ai to toolsPolicy.overrides.

Q: Can the review sub-agent also make tool calls? Would that trigger review again?

A: No. The review sub-agent runs in a sub-session via the fork provider; the plugin identifies review sub-sessions by session ID and directly goes through next() to skip review. Also, review only allows the three read-only tools read/glob/grep—it cannot write, run shell, or call other sub-agents (limited by maxDepth).

Q: What if the review crashes?

A: It goes to fallbackPolicy, defaulting to rejected—conservative denial with the review failure reason fed back to the main model. If you want humans to handle it, set fallbackPolicy to delegate; if you want to treat failure as success, set it to allow-once (README explicitly marks this as a dangerous option only for unattended deployments, with unconditional grant).

Q: Can I temporarily disable it?

A: Yes. Run /auto-review off in the session; the disabled state is written to session logs and remains effective on replay. /auto-review status shows current status, current turn budget, cumulative stats, and circuit status; /auto-review approve [n] grants one-time allow for the n-th most recent denial.

Q: Does it write to session logs? Can I audit afterward?

A: Yes. The chain approval/asked → autoReview/verdict (or autoReview/rejection) → approval/decided for each approval request can be reconstructed from session logs. Early harness versions (0.1.0-rc.1 ~ rc.7) lose the ignorable tag, so the plugin does capability probing before the first write; if probing fails, it auto-downgrades to in-memory audit with a one-time reminder, and you can use scripts/repair-session-logs.mjs from the dsh-permission-rules repo to fix already-polluted historical logs if needed.

Q: What's the difference between risk level policy and deny circuit breaker?

A: Risk level policy applies to individual verdicts: if review returns allow but riskLevel exceeds maxAutoAllow, that allow gets upgraded to delegate or deny; the circuit breaker applies to turn-level accumulation: 3 consecutive denials, or 6 denials in the last 10 verdicts, triggers the circuit, and subsequent requests in the turn follow the preset action (delegate/reject/abort-turn). They're not mutually exclusive.

Q: Where is data stored? Does it connect to the internet?

A: No local files, no extra network requests. Audit data stays in memory + session log (bounded by buffers like MEMORY_DENIES_CAP=200 / MEMORY_OVERRIDES_CAP=50). If reviewerModel is empty, it inherits the current session model; if you switch to another provider, you're essentially presenting the displayed session content to another provider—use your own judgment.

Q: How to uninstall?

A: dsh plugin --profile web remove dsh-auto-review, or delete the auto-review line from the profile patch; manifest marks transactional uninstall, leaving profile config untouched.

Difficulty Level

Advanced — requires understanding DSH's approval chain, risk rule regex, and session log audit events; you'll need to tune risk policies and circuit thresholds in cordis.yml to get full value. However, it works fine with just the default config.

Known Issues and Limitations

  • Early Harness Compatibility: @deepseek-ai/dsh-session in versions 0.1.0-rc.1 ~ rc.7 doesn't recognize the ignorable tag, which causes autoReview/* events to make stricter harnesses unable to resume the session. The plugin defaults to pre-check and downgrade to in-memory audit (functionality intact but no audit log). For persistent audit, set allowUnmarkedAudit: true (dangerous) or use the repair script from dsh-permission-rules to fix historical logs (CHANGELOG.md:9-17 / src/audit.ts:36-52).
  • Review Model Needs Working LLM Routing: Review inherits main session model routing by default; when routing fails, every review goes through fallbackPolicy—never silent allow (README.md:232-241).
  • reviewerTools Must Be Non-Empty: An empty whitelist leaves the review sub-agent with no tools, causing load-time error; tool names in the list must be globally registered in the profile, otherwise the review sub-agent fails on startup.
  • /auto-review approve Authorizes "Next Same-Tool Review" Not Historical Call: If the next same-tool call has different parameters or context, the authorization is still consumed, and review still judges based on that context (README.md:236-237).
  • never Is a One-Way Lock: Matching never policy denies directly, never entering the human chain—it's a lockdown knob, not a daily option (README.md:230).
  • Git Channel Install Needs pnpm.allowBuilds: { esbuild: true }: pnpm 11 ignores package.json#pnpm field, must write allowBuilds in pnpm-workspace.yaml (repo ships with this). typescript + tsdown are in regular dependencies to ensure git-isolated prepare environment can install them.
  • Invariant Companion Requires invariants Service: Only works under headless/ACP agent-spene composition; regular web profile lacks this service, so the companion patch is commented out by default in the repo.

Read the usage guide →

Install steps, key points, FAQ and compatibility for this plugin — auto-derived from indexed fields.

Listing badge

Listed on deepseek-plugin.org
[![Listed on deepseek-plugin.org](https://img.shields.io/badge/listed_on-deepseek--plugin.org-007EC6)](https://deepseek-plugin.org/plugins/PerryLink/dsh-auto-review)

Paste this markdown into your GitHub README to link back to this listing. The badge only states the listing — not a security endorsement.

← Back to plugin directory