ttxs66666/dsh-review-gate ↗★ 1
@dsh-external/dsh-review-gate
Hand finished derivations and code to an independent reviewer subagent and feed the verdict back to the main model. 把设计推导与代码成品交给独立审查子代理,并把结论回注给主模型。
安装
npx -p @deepseek-ai/dsh dsh plugin --profile web add github:ttxs66666/dsh-review-gate说明文档
阅读完整 README ↗dsh-review-gate
English | 中文
Hand finished derivations and code to an independent reviewer subagent, and feed the verdict back to the main model.
Trigger authority stays with the model. The plugin auto-sends nothing and guesses nothing from keywords: it injects two editable reminders and exposes one explicit tool.
- A — periodic reminder. Every N real user messages (always on a session's first message;
0injects on every message), remind the model to hand math derivations, research code, and paper drafts to a subagent for independent review, and to fix according to its findings. - B — research discipline. Text appended to the outgoing prompt when a review is dispatched: every parameter must have a reason — nothing may appear or be assigned without stating its source, unit, and valid range.
review_gate_check— the model (or a human) explicitly requests one review. A child subagent is dispatched, and its structured verdict (pass/needs_fixes/fail, with findings and required fixes) is rendered back into the conversation.
Install
dsh plugin --profile web add github:ttxs66666/dsh-review-gate
Restart dsh web afterwards. Requires DSH on the @deepseek-ai/dsh-* 0.1.x line, 0.1.5-rc.1 or newer (^0.1.5-rc.1 || ^0.1.6-rc.1 — the explicit prerelease branches are there because a range without one silently excludes every prerelease build; see peerDependencies).
What you get
Three surfaces, all bound to the same settings namespace, so they can never disagree:
| Surface | Slot | Contents |
|---|---|---|
| Settings → Review Gate | settings.section (id review-gate, order 60) | The full page: master switch, A/B toggles and texts, injection cadence, reviewer configuration (provider / persona / tool whitelist / artifact limit / logging / log path), composer-toggle visibility, in-process stats polled every 5s |
Composer + menu | conversation.input.left | A/B quick toggles, hidden by the page's + switch |
| Settings → Plugins | settings.plugin.item (key review-gate) | Compact card: status, master switch, pointer to the page |
Screenshots (optional, for storefronts): drop
assets/screenshot-1.png… into your repository and list them inscreenshots.jsonnext topackage.json—["assets/screenshot-1.png"], 1–8 entries, paths relative to that file.
Settings
Namespace review-gate (applies: live — every change takes effect immediately, no restart).
| Group | Fields |
|---|---|
| A / B | enabled injectA injectB promptA promptB promptAEvery showComposerToggles |
| Reviewer | provider reviewerPersona reviewerTools maxArtifactChars verboseLog logFile |
The reviewer group resolves as schema defaults → this plugin's composition config (base layer) → user layer: a value set in your profile config stays the effective default, the settings page overrides it, and clearing a field falls back to that config.
Host route: GET /review-gate/api/status (loopback only, no auth) returns the resolved settings, the available subagent providers, B's real delivery surface, and the process counters. The page shows host unreachable when the route does not answer, and host version is older when it answers without the newer fields (i.e. the host half has not been restarted yet).
Behaviour worth knowing
- The tool whitelist is resolved against the calling agent's scope. In a Web profile the tools live on an agent preset's standing scope rather than in the global layer, so a tool that exists can still be invisible to a global lookup. Names that are not visible are skipped with a log line; if the configured list is non-empty but entirely invisible, the review is refused instead of silently degrading into "no restriction". Dispatch itself retries with decreasing capability, so a whitelist the runtime rejects cannot fail the whole review.
- Provider capabilities are gated before dispatch.
persona,toolFilterandoutputSchemaare only sent to providers declaring them; whenpersonais unsupported the role text is prepended to the prompt instead, and the verdict says so. - B's reach is reported, not assumed. Kernels since 0.1.5-rc.1 removed
subagents.registerContinuableSetup, so B currently reaches review subagents only; the status API reportsreview-onlyand the page renders that truth. If the API returns, the plugin goes back tocontinuable+reviewby itself. - Counters live in process memory and reset when the plugin reloads.
Development
npm install
npm run check # typecheck + build + smoke probes
npm run build # host (tsc) → lib/index.js, client (tsdown) → lib/client.js
npm run probe # zero-dependency smoke probes against the built artifacts
lib/ is committed on purpose: DSH installs plugins from a git checkout without running a build, so the shipped bundle has to be in the repository. After changing src/, run npm run build and commit lib/ together with it.
To develop against a local checkout instead, npm run build:sh links the peer dependencies out of an installed DSH (DSH_CHECKOUT= bash scripts/build.sh) and then compiles both halves.
The probes under test/ are plain node scripts. probe-review-gate.mjs drives the compiled host half through a fake context (whitelist resolution, config-error routing, capability downgrade, malformed verdicts, counters); probe-client.mjs renders the compiled client half through a miniature React with a fake window/fetch (all three surfaces, plus both host-status paths). test/fixtures/quota-design.ts is not part of the plugin — it is a deliberately flawed derivation kept around to exercise the gate itself.