PerryLink/dsh-plugin-doctor ↗★ 2

@perrylink/dsh-plugin-doctor

Zero-dependency static + sandbox smoke detector for DeepSeek Harness (dsh) plugins: package-structure gates (R), cordis contract scans (K), keyless-headless sandbox smoke (D), and ecosystem-listing checks (CC). 适合需要对DSH插件进行结构、契约及沙箱运行安全检测的开发者。

パッケージ
@perrylink/dsh-plugin-doctor
互換性
未検証
バージョン
0.4.5
ライセンス
Apache-2.0
最終更新
2026/09/28

インストール

$npx -p @deepseek-ai/dsh dsh plugin --profile web add github:PerryLink/dsh-plugin-doctor

ドキュメント

README 全文を読む ↗

Usage

node doctor.mjs --repo             # 全量(含动态冒烟,需网络 + pnpm)
node doctor.mjs --repo  --no-smoke       # 仅静态 + 清单
node doctor.mjs --repo  --dsh 0.1.7-alpha.1 # 冒烟宿主版本(默认 npm latest 已发布线)
node doctor.mjs --repo  --only R,K       # 只跑静态两层(推荐用 ASCII 别名)
node doctor.mjs --repo  --json report.json
node doctor.mjs --repo  --json -         # JSON 写 stdout(此时抑制人类可读报告)
node doctor.mjs --repo  --format check --json -   # 生态三值契约视图(PASS/WARN/FAIL + 0/1/2)
node doctor.mjs --repo  --workspace    # 指定兄弟仓所在工作区(CC 组核对用)
node doctor.mjs --repo  --allow-degraded # 显式接受「整组未真跑」(默认 exit 6)
node doctor.mjs --purge               # 清理本工具产生的隔离目录(仅 doctor-quarantine-*)

Target shapes and coverage (new in 0.2.0)

--repo may be a source tree or an installed package directory / unpacked tarball artifact (the latter is common at node_modules/ ). The criteria change with the shape:

ShapeK group (Cordis contract)Notes
Source tree with src/scans src/** plus root-level JS (mode: src)complete
No src/, main points at lib/fallback scan of lib/** (mode: lib-fallback)fixed in 0.2.0: the old implementation keyed on "no build script", but published packages keep their build script → the fallback never fired, all nine K checks were skipped, and it still exited 0 (false green)
Neither src/ nor lib/all nine skipped (mode: none)the whole group never really ran → exit code 6, no more false green

Coverage is written to coverage.K in the JSON ({filesInspected, mode}) and summarised in groups.K.

--only groups and ASCII aliases

AliasFull group nameContents
Rstatic · package structureR0–R8
Kstatic · Cordis contract scanK1–K9
Ddynamic · sandbox smokeD0–D3, D9
CCecosystem · directory listingsCC1–CC5

Aliases are case-insensitive, and the Chinese full names still work. Use the aliases in workflows: if an editor or script round-trips a Chinese group name through the wrong encoding, --only matches no group at all.

Exit-code contract

CodeMeaningIntroduced
0no fail/error (warn/skip allowed), and every requested group really ran0.1.x
1fail/error present (a plugin defect)0.1.x
2usage error, unknown group, unknown option0.1.x
3infrastructure error (missing npm/pnpm and the like)0.2.0
4unsupported host version (the host itself failed to install; not a plugin verdict)0.2.0
5unstable result (a step timed out or was killed by a signal)0.2.0
6degraded: a requested group never really ran (e.g. no source files to scan)0.2.0

Guarding against silent passes (two layers):

  1. If even one group name in --only fails to match → immediately 2. Versions 0.1.4 and earlier would "check nothing + exit 0" when a group name was mangled, which once turned the CI gates of 35 repos into false green (measured 2026-09-09: checks_run=0, exit=0).
  2. From 0.2.0: a requested group whose checks all skipped → 6. The old implementation only covered "not a single check ran", not "it ran but everything skipped" — the latter let "K group with zero coverage" count as a pass. To accept that explicitly, use --allow-degraded (exit code drops to 0, but degraded stays non-empty in the JSON).

⚠️ The existing gates in 41 family repos do not read the exit code (their workflows use set +e / out="$(…)" / set -e) and only parse the R0 / K1 prefixes on stdout and results[].name in the JSON. So 0.2.0's new exit codes change nothing for those pipelines; they serve interactive use and future integrators.

  • The smoke run keeps its temporary DSH_HOME/DSH_AGENTS_HOME inside a self-made %TEMP% sandbox (prefix doctor-, which does not overlap the host-protected %TEMP%\dsh-* template) and never touches the real ~/.dsh (red line 3).
  • dsh plugin add is always passed --ignore-scripts: the tested package's install/prepare scripts never execute on the host. A pnpm ignored-builds block is classified as environment (it counts neither as a pass nor as a plugin defect).
  • Every step's subprocess stdout/stderr is written to %TEMP%\doctor-run-*\logs\; at the end the run quarantines instead of deleting (renames to %TEMP%\doctor-quarantine-*), prints that path in the report tail, and leaves removal to --purge after a human confirms (red line 4, the three-stage rule).
  • Absolute paths seen at runtime are placeholder-ised to before they reach the JSON or the rendered text, so a report can be committed into someone else's repo without tripping its path-leak gate.