DeepSeek Harness Plugin Hub

发布与管理完整 Harness Profiles,发现适合你的插件。

探索

插件目录环境预设文档中心动态

社区

发布插件联系我们报告问题

相关链接

Plugin Hub GitHubDeepSeek Harness 官方项目系统状态隐私说明
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

独立、非官方社区项目,与 DeepSeek 官方无隶属、授权或背书关系。

Decision Gate — DeepSeek Harness 插件(DSH Plugin)
DeepSeek Harness Plugin Hub
ProfilesPlugins分类动态文档登录管理 Profiles
ProfilesPlugins分类动态文档登录
← Plugins
D

dsh-decision-gate

Decision Gate

DSH PreToolUse 决策门禁——在每条 shell 命令执行前回答五个问题,然后允许、询问或拒绝。支持可替换的判定后端、按路径限定的豁免、JSONL 决策日志,以及用于已批准不可逆步骤的预授权列表。

插件会安装到这里;不确定时保持 web。

npx -y @deepseek-ai/dsh plugin --profile web add github:SeasonTemple/dsh-decision-gate#5764fe52f8f203cb43067d8d62a220a5bda89ded
README兼容性版本

兼容性与来源证明

Decision Gate 以 dsh-decision-gate 发布,当前版本为 0.5.1。Plugin Hub 会校验它的 manifest,并保存精确安装来源,便于复现安装结果。

DSH 兼容范围
*
运行环境
web
发布来源
github
Registry 更新时间
2026/10/19

版本

0.5.1stable
2026/10/19

相关插件

正在加载相关插件…

最新版
0.5.1
DSH
*
HMR
重启进程
Tree shaking
未声明可安全裁剪
解包体积
未提供
文件数
未提供
Surface
web
许可证
BUSL-1.1
发布源
github
GitHub
★ 1
周下载
0
最近提交
2026/10/19
查看源码 ↗
README Badge

点击下方 Badge 复制 Markdown,粘贴到 README 即可。

这是你的 Plugin?认领权益 · 优先安全扫描

验证 package.json 声明的 GitHub 仓库,即可管理这个公开页面。认领后,Hub 会优先安排当前版本的安全扫描,并在通过后公开展示结果。

认领这个 Plugin →
报告问题

相关插件

继续浏览 security-access 分类下经过校验的插件。

Experimental Auto Review@deepseek-ai/dsh-experimental-auto-review针对每个工具的 LLM 授权审查,适用于 DeepSeek Harness Auto 权限预设Cc Safety Netcc-safety-net编码代理 CLI 钩子——阻止破坏性命令和访问机密文件Doctor@linxin666/dsh-doctorDSH 配置档案的事务性救援模式,配备受监督的启动器、隔离的恢复容器、确定性修复、健康监控以及本地 Web 恢复控制台Pocketdsh-pocket把 DeepSeek Harness 装进你的口袋:一个包、一个设置页,手机扫码即同步访问电脑上的 DSH(局域网 + 公网,实时同屏)。

README

dsh-decision-gate

A PreToolUse decision gate for DSH — asks five yes/no questions about every shell tool call, then allows, asks, or denies it, with a swappable judge backend.

Calibrated thresholds, a path-scoped exemption, and a JSONL decision log — because a gate that cannot reach its judge must never become the thing that blocks the harness. How it works →

English · 简体中文 · How it works · Judge backends · Install · Verify · Changelog


A DSH (DeepSeek Harness) PreToolUse gate. Before every shell tool call (bash, pwsh, terminal_*) runs, the plugin asks a judge five yes/no questions about the operation, maps the answers through fixed thresholds to allow / ask / deny, and appends every decision to a JSONL log so the thresholds can be calibrated later against real data.

The gate has no power to escalate anything. Its one job is to stop the session from silently doing something a person would not have wanted — and to stay out of the way otherwise.

Version compatibility. Verified against DeepSeek Harness 0.2.1-rc.2 (the desktop RC): the in-process gate rides the tools/pre-execute seam that every RC since 0.2.0-rc.1 carries, and the supported range (>=0.2.0-rc.1 <0.3.0-0) is now declared in package.json engines.dsh — the field the harness's own plugin-compatibility gate reads, so an incompatible DSH skips this bundle loudly instead of loading it. The hooks.json form in this repo is the reference/regression twin, not the live gate; running it needs the optional @deepseek-ai/dsh-hooks-claude-code bridge, which the 0.2.1-rc.2 desktop build does not bundle (install it from the plugin market if you want that form). Requires Node >= 20.


How it works

For each gated tool call the plugin sends the tool name and arguments (clipped at 8000 chars per string) to TypeSafe's SystemOne endpoint with five noul questions:

signalwhat it asks
read_onlydoes this only inspect/read/display, changing nothing?
destructivewould this delete/overwrite data a person could not restore?
secret_exposurewould this send or print secret values anywhere?
external_irreversiblewould this change state outside this machine irreversibly?
routine_devis this a routine local development step?

The first rule that fires wins, in this order:

  1. secret_exposure >= 0.50 → deny
  2. destructive >= 0.50 → ask when exempt, otherwise deny
  3. external_irreversible >= 0.50 → ask
  4. read_only >= 0.80 → allow
  5. routine_dev >= 0.75 → allow
  6. otherwise → ask (unclear)

Every failure path — no API key, timeout, non-JSON answer, wrong answer shape — degrades to next() and logs the error. A gate that cannot reach its judge must never become the thing that blocks the harness.

Path-scoped exemption

The gate has no notion of context, so rm scratch-note.txt and rm -rf / score identically: destructive, deny, no approval channel. That leaves the agent permanently unable to clean up its own scratch files, because a deny cannot be overridden from inside the session.

Exemption fixes exactly that one case: when every path a command writes to lives inside an exempt prefix (default ['.agent-scratch']), the destructive deny is downgraded to an ask — a person still sees it, but the agent is not locked out. The parser is deliberately shallow and fails closed:

  • secret_exposure denies are never downgraded.
  • one non-exempt target disqualifies the whole command.
  • unknown verbs, unparseable quoting, cd then rm, find -delete, xargs rm, symlink escapes — all keep the original deny.
  • a write verb followed by more statements on later lines: a bare newline is whitespace, not a command separator, so the following tokens join the verb's argument list as extra targets — extra targets can only ever make a command less exempt, so this too fails closed. Keep destructive commands to a single statement when you want the exemption to apply.
rm -rf .agent-scratch/old-logs    # ask   (exempt_destructive)
rm -rf src                        # deny  (destructive)
cat .agent-scratch/keys.txt       # deny  (secret never downgrades)
rm .agent-scratch/a src/b         # deny  (one target outside the prefix)

Judge backends

The gate needs a model that answers five yes/no questions with probabilities. Two backends, chosen by the judgeProvider config key:

  • typesafe (default) — TypeSafe's SystemOne endpoint with calibrated noul probability questions: sub-second answers, and the thresholds mean what they say on that calibrated scale. Needs TYPESAFE_API_KEY, and some networks cannot reach it: a region-blocked egress gets HTTP 451 "not available in your region", which fails every call open. Configure typesafeProxy (or HTTP_PROXY/HTTPS_PROXY) to route around that.
  • dsh-llm — the same five questions go through the session's own LLM service, following the provider/model the DSH profile configures: no extra credential, no endpoint of its own, so no region or proxy question at all. The cost: every gated call waits for that model (pin a fast one via model / judgeRoute), and its self-reported probabilities are not on the calibrated scale the thresholds were tuned against.

Both backends converge on the same Signals object, so thresholds, exemption, and log format are identical whichever judge answers. A judge that errors, times out, or answers out of protocol fails open — the gate logs the reason and lets the call through.

Configuration

Config keys (profile cordis.patch.yml), all optional:

keydefault
judgeProvidertypesafe
matcher^(bash|pwsh|terminal_)
modelbackend-relative: jev-1.13.0 on typesafe; unset on dsh-llm means follow the session route
judgeRouteunset: follow the session's live provider/model; set {provider, model} to pin both
logPath<plugin dir>/decisions.jsonl
typesafeApiKeyunset: a role('secret') field, edited masked in the form and held by the credential store
typesafeApiKeyEnvTYPESAFE_API_KEY — the environment variable read when no key is configured
typesafeProxyunset: proxy URL for the typesafe endpoint (region-block workaround); empty reads HTTP_PROXY/HTTPS_PROXY, then connects directly
destructive0.50
secretExposure0.50
externalIrreversible0.50
readOnly0.80
routineDev0.75
exemptPrefixes['.agent-scratch']
authorizedOperations[] — commands whose external-irreversible ask is downgraded to allow, matched per statement

Auth: the dsh-llm backend needs no extra credential — it rides on the credentials DSH already resolved for the session's provider. The typesafe backend resolves its key by candidates, profile config first: typesafeApiKey (a role('secret') field — masked in the form, held by the credential store, never echoed) → the environment variable named by typesafeApiKeyEnv (TYPESAFE_API_KEY by default) → the Windows User environment (a legacy fallback, read once and cached). Configuring the key in the form is the intended path; the environment variable is the candidate for scripted deployments.

Every decision row records its judge backend and model; dsh-llm rows also record provider. A log that spans a backend switch stays interpretable.

Settings page

The plugin declares a schemastery Config schema, which the DSH settings service projects into this profile's configuration form (ctx.settings): the judge backend, pinned provider/model, matcher, log path, all five thresholds, the exempt prefixes, and the pre-authorized operations are editable as a form, validated on write, persisted into the profile patch, and applied by the Loader without a restart. The same keys keep working in cordis.patch.yml for scripted setups.

The card appears on the Plugins page's bundle detail, between the description and the component list.

The profile entry is the single source of truth: there is deliberately no environment-variable layer, so what the card shows is what runs — no second truth to drift. (The Python hook twin under hooks/ still reads DECISION_GATE_* environment variables; that is the hook form's only configuration channel and a separate deployment path.)

The schema needs @deepseek-ai/schemastery at runtime, resolved from the plugin's own location like any bare import (Node walks up from the module file). A normal npm install — including the one dsh plugin add performed into the profile — provides it.

Install

One command into any profile — the bundle's own patch mounts the gate, so there is no manual profile edit:

dsh plugin --profile web add E:/workspace/dsh-decision-gate

On the desktop app (whose profile the CLI refuses by design), use the same source through the in-app Plugins page: 添加插件 → 本地路径 → E:/workspace/dsh-decision-gate. Both routes link the package into the profile and select the bundle; the runtime dependencies @deepseek-ai/schemastery and undici resolve from npm.

Restart DSH (or the desktop app) and the gate is live with the defaults: the calibrated TypeSafe judge (TYPESAFE_API_KEY — from the card's secret field, an environment variable, or the Windows User environment), shell tools only, thresholds as below, .agent-scratch exemption. A region-blocked network (this one's direct egress gets HTTP 451 from api.typesafe.ai) additionally pins typesafeProxy in the profile's own patch row — the shipped bundle patch stays machine-neutral.

Configure

Every key has a default, so the zero-config install works. To override, add a row that targets decision-gate in the profile's cordis.patch.yml:

- id: decision-gate
  config:
    judgeProvider: 'dsh-llm'
    destructive: 0.4

Because the row is mounted by the bundle, the settings card renders read-only on a stock install — it still shows every effective value and judge health, which is the point of the card. A profile-patch row like the one above is both the configuration channel and what makes the card writable again.

Uninstall

dsh plugin --profile web remove dsh-decision-gate

One step — the row lives in the package, so removing the bundle removes the gate. Rolling back to the hook form instead: the hook version is the files under hooks/, registered through hooks/hooks.json.

Layout

lib/index.js          built host half (one runtime dependency: schemastery)
src/index.ts          plugin source
src/parity.ts         Python↔TypeScript decision parity harness
hooks/                Python twin (specification and regression baseline)
tests/                pytest suite for the Python twin + hook config
docs/decision-gate-setup.md  deployment and calibration record
AGENT.md              rules for agents working on this repo (not shipped)
examples/             probe payloads used by the live-path tests

The Python twin in hooks/ is the reference implementation the plugin was ported from; src/parity.ts replays its recorded baseline through the TypeScript side and asserts the decisions still match. hooks/exempt.py and the exemption code in src/index.ts mirror each other token for token, held to the same expectations by tests/test_exempt.py and the offline section of parity.ts — the two sides cannot drift apart silently.

tests/test_policy.py, tests/test_triage.py and tests/test_live_path.py (plus examples/) are inherited from the workspace this package was extracted from: they test the sibling noul-triage feature and import its muiltilab package. npm run test:py deliberately runs only the gate's own three test modules; run the full suite from a checkout that has the triage package importable.

Verify

node tests/functional.mjs   # 14 fake-context cases: both backends, fail-open, log
node src/parity.ts          # 26 recorded decisions + 30 exemption cases + 3 downgrade
                            # rules + 12 judge-output parses + 10 config shapes
python -m pytest tests -q   # Python twin + hook config

The offline sections of parity need no API key; the recorded-decision replay needs TYPESAFE_API_KEY.

During the calibration watch period, node tools/observe.mjs prints the decision distribution, judge error rate, near-miss allows (a dangerous signal below its threshold), and recent denials for false-deny review.

The deployment and calibration record — install paths, both config channels, the probe tables, and the periodic threshold reviews — lives in docs/decision-gate-setup.md.

License

Business Source License 1.1 — see LICENSE. Source is visible and free to copy, modify, and redistribute, and free for non-production use; production use requires a commercial license until the Change Date (2030-10-10), after which the work is available under Apache 2.0.