DSH Plugins Marketplace

DSH Plugins

Plugins

/

dsh-guard-degen

c

dsh-guard-degen

Manifest valid

Degeneration guard for DeepSeek Harness: contains runaway symbol streams at the model boundary and repairs polluted artifacts and sessions. 退化守卫:拦截模型输出退化符号流,修复被污染的工件与会话。

UI (client)hasBundlePatchMachine translated

dsh-guard-degen

CI npm

A degeneration guard for DeepSeek Harness: it contains runaway symbol streams at the model boundary and ships tooling to repair polluted artifacts and sessions.

Why

Some models (in our measurements, concentrated in the MiniMax family) degenerate their reasoning into a single repeated character:

⇒ ⇒ ⇒ ⇒ ⇒ ⇒ ⇒ ⇒ ⇒ ⇒ ⇒ ⇒ ⇒ ⇒ ⇒ …

Degeneration is not always one character repeated: a multi-character unit can repeat as a whole block over and over:

⇒⇒§ ⇒⇒§ §

⇒⇒§ ⇒⇒§ §

… (the same block, again and again)

That output is persisted into session files and can even be written by the model into repository documents and source files. Once a session is polluted, "continue" only yields more of the same stream — the session is unusable, but the file pollution survives into the next session and accumulates.

This plugin does four things:

  1. Stream containment — detect symbol runs before the output reaches the UI, and truncate/sanitize/remove according to policy.
  2. Write verification — after a write-type tool runs, read the file back; if it is polluted, block the result and feed the finding back to the model.
  3. Retry and model switch — retry a failed request (same model, N times) and optionally switch to an explicitly configured model.
  4. Artifact and session cleanup — scan the workspace and session history, produce a report, and let you pick what to repair (preview only by default; nothing is written).

The stream guard has four policies, set separately for the reasoning channel and the text channel:

PolicyWhat happens to the degenerate run
offNothing is detected or changed — the run goes through untouched.
truncate (default)The channel is cut and the round ends with a "degeneration" error.
sanitizeThe run is folded into a marker (〔退化符号流×N〕) and the round continues.
removeThe run is deleted outright — not one marker is left behind — and the round continues.

remove is the quietest option: the model output reads as if the degenerate segment had never been written. The removed text is still recorded in the verdict journal as evidence, but unlike sanitize it cannot be reverted — there is nothing in the stream to put back.

Artifact governance covers both shapes: a run of one symbol, and a multi-character unit repeated as a whole block. After ticking the entries you want, "preview repair" shows a red/green diff (red = before the repair, green = after it) right in the view, so you can confirm before anything is written to disk.

The multi-character unit shape is governed in four places, each with its own switch and its own repetition threshold:

PlaceSwitchThresholdDefault
Artifact repairartifacts.unitRunartifacts.unitRepeatson / 4
Stream guardstream.unitRunstream.unitRepeatson / 4
Tool guardtoolGuard.unitRuntoolGuard.unitRepeatson / 4
Session maskingsessions.unitRunsessions.unitRepeatson / 4

Turning a switch off leaves that place with the single-symbol run rule only; the other places keep their own setting, so the four guards never drag each other along. The thresholds are independent too: raise one to be more permissive, lower one to be more sensitive, without touching the others.

Install

One command (the package is published on npm):

dsh plugin --profile <your profile> add dsh-guard-degen

Replace <your profile> with the profile the host actually uses (web for dsh web; the desktop app uses its own profile, whose name is not necessarily the same).

Or install straight from the repository:

dsh plugin --profile <your profile> add github:chunqing286/dsh-guard-degen

Or do it in the UI: Plugins → Discover, add the index source https://cdn.jsdelivr.net/npm/dsh-plugin-catalog/index.json, search for "degeneration guard", and press Install.

Either way the package's own cordis.patch.yml is applied as a bundle layer, so the host half and the browser half go in together; the Degeneration guard section shows up in Settings as soon as the host reloads.

Manual install

If you would rather not use a package manager, append one insert to $DSH_HOME/profiles/<profile>/cordis.patch.yml:

- insert:
    - id: guard-degen
      name: <relative path to the plugin directory, or a package name>

Relative paths in name are anchored beside the patch file (documented host semantics), so any local directory works; a bare package name must be resolvable from the profile's node_modules or the installation's own packages.

With a relative-path install the plugin directory must resolve its own runtime dependencies (@deepseek-ai/dsh-typert-protocol, @deepseek-ai/schemastery, plus @deepseek-ai/cordis and @deepseek-ai/cosmokit that they pull in); an npm install pulls those in for you.

The profile bundle mechanism works too: list "dsh": { "profile": { "bundles": ["dsh-guard-degen"] } } in the profile manifest and add the package to dependencies — the package's own cordis.patch.yml is then applied as a bundle layer.

The host plugin exposes a native Schemastery Config schema, so the settings page renders a form automatically. The plugin also registers its own Settings → Degeneration guard section (a sibling of Plugins) with three tabs under it, each on its own page (they never render on top of each other):

  • Config — graphical entry points for every setting.
  • Logs — the verdict log: every degeneration verdict records which rule fired, in which session, and what the guard did about it. Every row carries the session ID and the session name, and the list can be filtered by session (pick one from the dropdown, or type part of a session ID / name). Selecting a row shows the detected degeneration features (which unit repeated how many times) and the red/green diff of the remediation (red = the degenerate text before, green = what is left after: the collapse marker when the output was sanitized, an explicit "nothing was left behind" note when it was removed, an explicit "nothing follows" note when it was truncated, and "recorded only, not remediated" when the guard did not rewrite anything). False-positive feedback lives here too.
  • Artifacts — the artifact scan report and the list of polluted sessions; select entries, then preview and apply the repair. The repair preview is rendered as a red/green diff per file (red = the polluted text before the repair, green = the marker or empty result after it).

The session list shows both the session title and the session id. After "preview masking", the page renders the change inline as a red/green diff (red = original text, green = the marker that replaces it), so there is no need to open the generated file on disk.

Session masking has two content modes, selectable on both the artifacts page and the session view:

  • Collapse — fold the degenerate run into 〔退化内容已遮蔽×N〕.
  • Remove — delete the run entirely (default). Nothing is written in its place: the file ends up with the symbols gone, and the green diff line shows the text that remains after the deletion (not a sentence standing in for the run). When the whole content was degenerate, the green line says so explicitly.

Switching the mode recomputes the preview immediately, so the change can be inspected before anything is written.

Masking also has two landing modes, selectable on both pages:

  • Write a separate copy — the masked content lands in a new file, the archive stays untouched.
  • Rewrite the session archive in place — the default on both pages: the session you are looking at is masked itself (the original is backed up first), no copy to hunt for.

The guard view inside a session

The session page's view row (next to Chat / Trajectory / Context / Squad) also carries a Degeneration guard view, scoped to the current session:

  • Workspace artifacts — the scan range is the working directory of the current session (the host resolves it from the session archive header; the browser only sends the session id and can never pick a directory), and the repair covers the artifacts in that directory.
  • Current session — mask the degenerate content of the session itself, with the same modes as the artifacts page.

"Apply masking" rewrites the current session in place by default: the archive is replaced atomically (temp file, then rename), the original is backed up to ~/.dsh/guard-degen/backups/, and the written file is read back and verified.

Three things are worth knowing:

  • The messages on screen do not change right away — the chat view is served from the host's memory; reopen the session to see the rewritten text.
  • A running session keeps appending — new messages are still appended after the rewritten content.
  • The masking is recomputed on the latest content — if the session was written to after the preview, the plan is recomputed so that new messages are not dropped.

Commands

CommandEffect
/degen-statusGuard status, rule table, recent verdicts
/degen-scan [paths…]Read-only artifact scan (defaults to the workspace)
/degen-fix <file…>Repair the given files (backs up before rewriting)
/degen-cleanMask degeneration in the current session (rewrites the archive in place by default)
/degen-ackRecord the latest verdict as a false positive and relax that rule one step

Configuration

KeyDefaultMeaning
enabledtrueMaster switch
modelIncludes[]Guard only these models (empty = all)
stream.reasoningtruncateReasoning policy: off/truncate/sanitize/remove
stream.texttruncateText policy: off/truncate/sanitize/remove
stream.holdbackChars256Characters held back before a verdict
stream.maxInterventionsPerCall1Max interventions per call
stream.unitRuntrueAlso govern multi-character units repeated as a whole block
stream.unitRepeats4How many repeats of a unit count as degeneration (stream guard)
toolGuard.modewarnDegeneration in tool arguments: off/warn/refuse
toolGuard.scopeallall/write-only/oversized-only
toolGuard.unitRuntrueAlso govern multi-character units in tool arguments
toolGuard.unitRepeats4How many repeats of a unit count as degeneration (tool guard)
postExecute.enabledfalseWrite-back verification (costs IO)
postExecute.roots[]Restrict verification; empty = inside the workspace
retry.policysame-modelsame-model/steer/no-retry
retry.maxSameModelRetries1Same-model retry count
retry.switchModel.enabledfalseAllow an automatic model switch
artifacts.moderemovecollapse (marker) or remove (delete the run)
artifacts.applyfalsePreview only by default
artifacts.unitRuntrueAlso govern multi-character units repeated as a whole block
artifacts.unitRepeats4How many repeats of a unit count as degeneration
artifacts.maxFileBytes8388608Per-file size limit; larger files are skipped (and listed)
sessions.modereplacecopy (new file) or replace (rewrite in place)
sessions.maskModeremovecollapse (marker) or remove (delete the run)
sessions.unitRuntrueAlso govern multi-character units in session content
sessions.unitRepeats4How many repeats of a unit count as degeneration
logging.enabledtruePersist the verdict journal

Runtime edits are written to ~/.dsh/guard-degen/config.json, layered over the profile configuration.

Safety boundaries

  • Read-only by default: artifact repair and session masking default to apply=false; the preview phase writes nothing.
  • Back up before rewriting: a real write produces <file>.degen-backup first; if the backup fails, the original file is left untouched.
  • Read-back verification: after rewriting, the file is read again and the residual runs are counted; a non-zero residual is reported as an error rather than a success.
  • Runs, not single symbols: legitimate markers such as ★ exist in real repositories, so only runs of a symbol count as degeneration.
  • Multi-character units only count in symbolic regions: a block like ⇒⇒§ ⇒⇒§ § repeated end to end is a separate degeneration shape (marked 〔退化单元×N〕). The unit must contain at least one non-ASCII character, so code, tables and normal prose are not misjudged; a run of one symbol stays the business of the run rule, so nothing is reported twice.
  • The leftover fragments are judged too: degenerate content often alternates a long run with fragments (⇒⇒⇒⇒… ⇒⇒⇒⇒… **⇒⇒ **). Removing the runs makes the fragments touch, and they can form a new multi-character unit repeat. The unit rule therefore judges the fragments left after the runs are taken out, so one repair pass clears both — otherwise the read-back verification would reject the result with "verification failed" and the user would get nothing.
  • The browser cannot widen a threshold: the run length, the symbol set and the unit thresholds come from the configuration, never from the browser request; a page that asks for a looser threshold than the configured one is ignored.
  • Tool-call arguments are preserved: session masking keeps tool-call blocks byte-identical (their pairing must not break), which means roughly 24% of the polluted symbols — the ones inside tool arguments — are intentionally left in place.
  • Only model-produced content is rewritten: masking touches the text and reasoning of assistant/message events (and compaction summaries); user prompts, system messages and tool results are left byte-identical.
  • No writes outside the roots: artifact scanning and repair are bound to artifacts.roots (the working directory by default); an explicit file list cannot bypass the roots, and symlink targets and non-UTF-8 files are skipped. /degen-fix binds each run to the directories of the files you named, so pointing at a file outside the workspace still works — but nothing else in that tree is touched.
  • The browser cannot pick write targets: remote methods only forward allow-listed arguments; output, backup and audit paths are decided by the plugin. Masking copies, backups and audits are written to ~/.dsh/guard-degen/{masked,backups,audit}/, never into the session directory. Masking only accepts targets under ~/.dsh/sessions.
  • Nothing to mask, nothing written: if a session holds no degenerate run, masking leaves the archive byte-identical and creates no backup.
  • A run that spans two blocks cuts the stream: the host pushes deltas block by block and offers no way to retract what was already released. When the head of a run has already been released, the guard therefore cuts the stream instead of folding only the tail — a half-folded marker would both under-count the symbols and leave raw symbols in the text. The cost is a truncated answer, which is the right failure mode: the session was going to be restarted anyway.
  • The marker count matches the text: the block-end text is authoritative in the host assembler, so the 〔退化符号流×N〕 marker is rewritten in it too — the count in the archive equals the number of symbols actually removed.
  • Symlink targets are never masked: a session target that is a symbolic link is refused outright (even when it resolves inside the session root), and the root check compares real paths, so a link inside the root cannot rewrite a file outside it.
  • The intervention cap truncates instead of leaking: when the per-call rewrite budget is used up, the stream is cut with an error finish — the raw symbols never reach the conversation.
  • Bad configuration never lands: setConfig validates the merged result first and refuses to persist invalid values.
  • Skipped files are called out: files over artifacts.maxFileBytes (8 MB by default) are not inspected; they are listed in the report's skippedTooLarge and shown in the GUI — "not scanned" must never read as "clean".

Development

node --test test/*.test.mjs

The suite does not require the host runtime (apart from a few integration checks that use the real cordis package).

Standalone checks live in verify/ (run them with the same node binary):

ScriptWhat it proves
check-patch-config.mjsthe bundled cordis.patch.yml matches the schema defaults
check-host-load.mjsthe host class instantiates in the real cordis and exposes all 13 remote methods
check-host-entry.mjsthe host half loads on real cordis and wires its listeners
check-remote.mjsthe remote-method markers are recognised by the real protocol package
check-package-files.mjsthe package manifest points at files that exist (npm pack --dry-run equivalent)
check-mutations.mjsevery fix is pinned: reverting it turns a test red
check-remove-mode.mjs"remove" masking leaves no trace on disk

Comments

Loading…

Similar plugins

dsh-output-loop-guard

by ADistanceThereIs

DSH guard against self-repetition in streamed model output: detects a degeneration loop in reasoning or visible text, aborts the runaway turn and wakes the agent with a corrective notice.

Tools & CapabilitiesManifest valid

★ 0

MIT

JavaScript

Oct 16, 2026

dsh plugin --profile web add dsh-output-loop-guard

by bluemika111

DeepSeek Harness 插件:检测模型思考段的复读退化并自动打断、自动续跑。通用重复检测,不依赖白名单。

Terminal & ClientsManifest valid

★ 0

MIT

JavaScript

Oct 20, 2026

dsh plugin --profile web add dsh-degeneration-guard

by lyc0110

Guardrail for DSH llm/stream: detects when model reasoning or text degenerates into a periodic repetition loop and aborts the request instead of streaming until you give up.

Manifest valid

★ 0

MIT

JavaScript

Oct 21, 2026

dsh plugin --profile web add dsh-loop-guard

by DeLightor

Dependency-topology guard: pre-install conflict prediction and post-install detection of duplicate @deepseek-ai/dsh-* copies, version drift, and vendored core services that cause Symbol-key crashes li

Tools & CapabilitiesDevelopment & InfrastructureManifest valid

★ 0

MIT

JavaScript

Aug 16, 2026

dsh plugin --profile web add dsh-depguard

by zqh260619

DSH(DeepSeek Harness)实时重复输出守卫:模型复读时立即停止生成(默认同一字符串连续重复 ≥10 次;阈值、单元长度、检测窗口、白名单等全部参数可在设置页动态调整)。已生成内容正常提交,不丢消息、不污染会话日志。Real-time repetition guard plugin for DSH, with a graphical settings page and npm one-command install.

Security & AuditDevelopment & InfrastructureManifest valid

★ 3

↓ 426/wk

MIT

JavaScript

Oct 26, 2026

dsh plugin --profile web add dsh-dupguard

by dingchenhui0618-arch

Adversary review gate for DeepSeek Harness: an independent small model reviews destructive tool calls before they run, and reports every verdict. · DSH 对抗式审查门:危险工具调用在执行前由一个独立小模型复核。

Security & AuditTerminal & ClientsManifest valid

★ 0

MIT

JavaScript

Oct 27, 2026

dsh plugin --profile web add dsh-warden