Plugin-combination analysis for the DeepSeek Harness: dependency trees, conflict detection, risk scoring with prediction, visualization, and combination simulation.
Install
# from GitHub (first run asks for allowBuilds approval — follow the hint, retry)
dsh plugin --profile web add github:mkiea/dsh-forge
Any plugin you install runs third-party code with your own permissions — it can read your files, use your credentials, and reach the network, and tool approvals don’t sandbox it. GitHub-sourced plugins also run build scripts at install time — pnpm blocks those until you allow them, so an install can stop with ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED or ERR_PNPM_IGNORED_BUILDS; dsh prints the exact key to add under allowBuilds in your profile’s pnpm-workspace.yaml, and the install works on the next run. Allowing a build is a trust decision: only install sources you trust, and pin a commit (github:owner/repo#sha).
README
Version: 0.1.14 (official) · harnessVersion: 0.1.1-rc.2
A plugin-composition analysis plugin for the DeepSeek Harness: dependency analysis, conflict detection, risk assessment (with prediction), visualization and combination simulation.
v0.1.11 patch: harness baseline bumped to the latest
0.1.1-rc.2—@deepseek-ai/dsh-tools^0.1.0-rc.6→^0.1.1-rc.2(defineToolAPI compatible), 13minimumReleaseAgeExcludeentries inpnpm-workspace.yamlsynced; the knowledge-graph verification baselinePATTERNS_HARNESS_VERSIONupdated, removing the falseknowledge-version-driftwarning on the newest deployment. 14 read-only tools,core/30 zero-dependency modules, 26 self-contained suites all pass.
Tools (14, all read-only; simulate_combination / archive_snapshot never touch the composition)
Analysis
| Tool | Description |
|---|---|
analyze_dependencies |
Dependency tree + shared-dependency summary + range satisfaction |
check_conflicts |
Version conflicts / tool-name collisions (scope-aware: per-agent variants legal) / service collisions / missing providers / row overrides / leak scan / runtime calibration (event-stream baseline) |
visualize_plugins |
HTML / Mermaid / ASCII / dashboard (interactive workspace, 8 modules) output |
simulate_combination |
Hypothetical combination: new/resolved conflicts, risk delta, verdict |
audit_configuration |
Per-row config audit (openAt / telemetry mode / in-memory paths / fetch, etc.) |
diff_combinations |
Row add/remove/change between two snapshots (or snapshot vs live) + risk delta |
preset_compare |
standard / code / minimal / cordis preset row-set & tool-surface comparison |
verify_rows |
Row mount preflight (package resolvable / dsh.client / client.js built) + runtime service probe |
Lifecycle
| Tool | Description |
|---|---|
archive_snapshot |
Archive the current combination to data/history |
snapshot_history |
List/load historical snapshots |
history_stats |
Trend statistics over snapshots (rows/health series; dashboard trend panel) |
Decision support
| Tool | Description |
|---|---|
suggest_patch |
Conflict advice -> cordis.patch.yml snippet (text only, never writes) |
check_upgrades |
npm registry latest-version check + upgrade-blocker prediction (concurrency pool + per-request timeout + mirror fallback + install commands, per-package network failures reported) |
plan_upgrade |
Upgrade-path prediction: before/after health, risk delta, newly-introduced vs resolved conflicts and concrete next steps when selected packages move to given (or latest) versions (read-only) |
Architecture
Three layers, see ARCHITECTURE.md:
core/ dependency-free engine (30 modules, Node built-ins only)
├─ composition.js composition discovery + YAML parsing + ecosystem collection
├─ truth.js dump-config ground truth (auto/dump-config/scan)
├─ analyze.js dependency graph + risk scoring
├─ conflicts.js conflict detection (version/tool/service/leak)
├─ scope.js scope awareness (global vs per-agent variants)
├─ calibration.js runtime event calibration (behavior baseline)
├─ leaks.js non-reversible side-effect leak scan
├─ semver.js SemVer parsing + range satisfaction
├─ upgrade.js npm registry upgrade check (pool + mirror fallback)
└─ ... audit / diff / simulate / visualize / dashboard / ...
src/ cordis plugin shell (src/tools/ per-tool modules, 14 tool schemas + registration)
ui-plugin/ browser client plugin (sidebar entry + modal dashboard)
Installation
Two packages, both persisted into the dsh profile via link dependencies (symlinks to source; code changes take effect per the dev-mode table):
- dsh-forge (host plugin): 14 analysis tools on the HOST plane
- dsh-forge-ui (client plugin): dashboard entry at the bottom of the right sidebar (below the session list / above Settings); clicking opens the dashboard modal (iframe-embedded
reports/dashboard.html)
Prerequisites
- Node.js >= 20 (tested on v24.18.0)
- DeepSeek Harness CLI installed:
npx @deepseek-ai/dsh --version - A target profile (default
web, at$HOME/.dsh/profiles/web/;dshdirectory is$DSH_HOME)
Step 1: Get the source
git clone https://gitee.com/mkieaAG367/dsh-forge.git
# or: git clone https://github.com/mkiea/dsh-forge
cd dsh-forge
Step 2: Persist into the profile (link deps, recommended)
The dsh profile is itself a pnpm workspace (package.json + pnpm-workspace.yaml); dsh plugin wraps pnpm. Use link: dependencies:
npx @deepseek-ai/dsh plugin --profile web add "dsh-forge@link:C:/Users/<you>/DeepForge/dsh-forge"
npx @deepseek-ai/dsh plugin --profile web add "dsh-forge-ui@link:C:/Users/<you>/DeepForge/dsh-forge/ui-plugin"
Use Windows absolute paths (forward slashes). Quote the specifier if the shell escapes
link:.
Equivalent manual way: add to $HOME/.dsh/profiles/web/package.json dependencies and run pnpm install in the profile directory.
Verify:
Get-Item "$HOME\.dsh\profiles\web\node_modules\dsh-forge" | Select-Object -ExpandProperty Target
Step 3: Patch the composition (cordis.patch.yml)
Append two insert entries to $HOME/.dsh/profiles/web/cordis.patch.yml:
- insert:
- id: forge
name: 'dsh-forge'
config:
profile: web
- insert:
- id: forge-ui
name: 'dsh-forge-ui'
config.profiletells the host plugin which profile to analyze;forge-uineeds no config. Do not append duplicate inserts (the harness would register the plugin twice). The profile rootcordis.ymlstays[]; edit only the patch file.
Step 4: Restart the harness
npx @deepseek-ai/dsh web
Success: no Cannot find module / schema (JsonSchemaError) errors, listening on http://127.0.0.1:3080.
Step 5: Verify
- Open
http://127.0.0.1:3080, no console errors - The sidebar shows the dashboard button below the session list / above Settings (opens the modal dashboard)
- The 14 tools are callable in conversation (
analyze_dependencies/check_conflicts/visualize_plugins/ ...) - Offline self-check:
cd dsh-forge && node --input-type=module -e "import('./src/index.js').then(m => console.log('plugin import OK:', m.name))"
Dev-mode change effects
| Change | How it takes effect |
|---|---|
Host plugin code (core/, src/) |
Must restart the harness (modules are cached; defineTool compiles schemas at apply) |
Client bundle (ui-plugin/lib/client.js) |
Symlink-synced instantly, but manifest/plugin-set changes need a restart |
Dashboard content (web/, reports/dashboard.html) |
node scripts/generate-dashboard.mjs (regenerate from the snapshot via the current dashboard.js) -> node scripts/build-ui.mjs (re-embed into client.js) -> restart |
| One-shot mount (no manual copy) | node scripts/mount-ui.mjs (auto-detects the deployment node_modules + copies ui-plugin + writes the patch; supports DSH_DEPLOY_NM / DSH_FORGE_ROOT / DSH_HOME / DSH_PROFILE_PATCH env overrides) |
Uninstall
cd "$HOME/.dsh/profiles/web"
npx @deepseek-ai/dsh plugin --profile web remove dsh-forge dsh-forge-ui
Remove the two inserts from cordis.patch.yml and restart the harness.
Composition discovery (host runtime)
Auto-discovery from $DSH_HOME/profiles/<profile>: profile root cordis.yml -> bundle patches (dsh-base / dsh-web-app, deployment root auto-located) -> cordis.patch.yml. Package manifests and installed versions are read from the deployment node_modules (no root needed). Overrides: compositionSources / dataset (offline snapshot) / root.
Offline snapshots
data/ecosystem.json is the analysis-time snapshot (format: dsh-forge-ecosystem@1); reproduce the same analysis with the dataset parameter.
CLI reproduction (no plugin runtime)
CLI / plugin shell / Web all load analyses through runAnalysisAsync() (dump-config first, falling back to scan only when unavailable, v0.1.14):
node --input-type=module -e "
import { runAnalysisAsync } from './core/index.js';
const r = await runAnalysisAsync({ profile: 'web' }); // prefers dsh --dump-config, falls back to source scan
console.log(JSON.stringify(r.assessment, null, 1));
"
For deterministic offline reproduction use the sync runAnalysis({ datasetPath }); the CLI loader loadAnalysisAsync() keeps the same dump-config-first preference.
Standalone CLI: TUI / Web / check (default TUI, web on demand)
The package exposes a dsh-forge bin (cli/dsh-forge.mjs). The UI shape is decided by core/mode.js from four evidence layers — never guessed:
- Launch command (hard signal):
dsh-forge tuiforces TUI;dsh-forge web|servestarts the web panel and opens the browser;dsh-forge check|ciprints logs /--json, no UI. - Runtime environment: TUI requires
stdout.isTTYandTERM != dumb; desktop sessions are detected viaDISPLAY/WAYLAND_DISPLAY/SESSIONNAME; no TTY but a desktop session selects Web; an occupied port degrades to TUI (interactive) or check (non-interactive). - User scenario: CI (
CIenv) and--jsonalways select machine-readable check mode. - Data complexity: < 10 plugins -> TUI; > 30 plugins -> suggest
dsh-forge weband allow one-key switch withWfrom the TUI.
node cli/dsh-forge.mjs # auto decision (TUI by default in a real terminal)
node cli/dsh-forge.mjs tui # force TUI (W=open web, R=refresh, Q=quit)
node cli/dsh-forge.mjs web # force Web (--port 3060, --no-open to skip browser)
node cli/dsh-forge.mjs check --json # CI/CD machine output
Both shells share the same core/ engine: the TUI is a zero-dependency ANSI renderer,
and the Web shell is node:http serving the interactive 10-module dashboard
(falls back to the self-contained SVG topology page when web/dashboard-client.js
is unavailable; no Express/ECharts dependency, keeping core dependency-free and
offline-deployable).
The Web form uses hybrid review: each request renders the dashboard fresh from
the current analysis (static layer), and the header ↻ Refresh button calls
GET /api/refresh to clear the analysis cache and re-analyze (dynamic layer), so
the dashboard always reflects the real combination without a page reload.
Verification status
dsh webruns at http://127.0.0.1:3080, no browser errors, 14 tools registeredanalyze_dependencieslive: 4 layers (profile root + dsh-base + dsh-web-app + patch), 138 rows (incl. forge/forge-ui) / 128 packages / 1226+ edges- Automated tests (26 self-contained suites; smoke13 13/13 depends on the local harness, not in CI):
test/ui-test.mjs— dashboard workspace structure & interaction (77)test/ui-plugin-test.mjs— client plugin VM execution + slot registration + modal interaction (22)test/semver-consistency.test.mjs— single-source SemVer regression + anti-mirror guard (30)test/review-fixes.test.mjs— scope states / event calibration / leak slicing (15)test/upgrade-opt.test.mjs— upgrade check concurrency/timeout/fallback/install commands (16)test/feedback-smoke.test.mjs— error-feedback smoke (40)test/empty-plugins.test.mjs— empty combination / leak rules (24)test/exploratory-empty.test.mjs— random subset exploration (27)test/exploratory-feedback.test.mjs— feedback deep exploration (563)test/mode-decision.test.mjs— four-layer TUI/Web/check decision engine (19)test/cache-behavior.test.mjs— runAnalysis cache invalidation/eviction/snapshot guard (7)test/tools-snapshot-smoke.test.mjs— 14-tool snapshot semi-integration + output.schema validation (14)test/composition-strict.test.mjs— YAML fail-loud + vm sandbox escape regression (8, incl. inline comments & cordis inject key)
test/evidence-fusion.test.mjs— evidence-fusion engine (A-1 three states + A-2 stable id + A-3 actionable + 7-row matrix + INV-3 never-clear, 18)test/runtime-calibration.test.mjs— runtime calibration (A-4 window/cardinality cap + INV-2 ordering + reversibility, 21)test/truth-source-degradation.test.mjs— truth-source degradation (INV-4 confidence cap, 12)test/check-report-schema.test.mjs— P0-3 frozen check --json report schema + gate (10)test/gate-lever.test.mjs— direction-4 gate lever (lever/blockedBy/degraded) + confidence tiers; frozen gate.pass preserved (12)test/gate-policy.test.mjs— direction-4 (option C) configurable gate policy (severity/tier/confidence -> block|warn|allow); contract conflicts stay strict even under scan cap; severity downgrades; frozen default preserved (11)test/finding-id-uniqueness.test.mjs— finding_id uniqueness regression (service/row/package dims + A-2 stability, 6)test/main-path-fusion.test.mjs— default-path fusion wiring (runAnalysis fuses conflicts/leaks with an offline not-executed baseline; finalSeverity/evidenceTag/runtimeState + INV-3, 8)test/heuristic-detect.test.mjs— heuristic-detection convergence (handle-aware leak scan + known-safe downgrade + leak-context + all BARE rules; per-package dynamic tool-name tracking + explicit scan limitation, 16)test/live-cal-unify.test.mjs— live-calibration unification (RUNTIME_LIFECYCLE_EVENTS event-name contract + dual-channel bridge dedup + honest offline degrade, 12)test/graph-test.mjs— dependency-graph suite (overview-filtered rendering / node-click pre/post details / synthetic edge connectivity / graph update after addRow, 23)
Error feedback
- Unified codes (FORGE-001~014) + severities (fatal/error/warning/info) + guidance + source.
- Dashboard "Errors & Feedback" panel; startup preflight prints fatal diagnostics to terminal stderr (crash-diagnosable).
- check_conflicts returns a
feedbackfield. - Dashboard entry: sidebar below sessions / above Settings (sidebar.footer.action) + turn-tail hint card; the header button was removed.
Review remediation (R0–R5)
The third-party PM review acceptance criteria are implemented item by item: dump-config ground truth (R0), calibration honesty + contract/heuristic split (R1), harnessVersion binding + knowledge version gating (R2), leak scanning (R3), evidence tiers static-suspect/contract-source (R4). See reports/PM-remediation.md and CHANGELOG.md.
Known limitations (honest)
| Limitation | Why | Mitigation |
|---|---|---|
| truthSource falls back to scan | no DSH_HOME set, or npx install tree paths don't fully match findDshBin candidates |
auto-detect ~/.dsh via resolveDshHome; if still failing, output truthSource=scan + explicit warnings |
| Static scan coverage limited | only lib/**/*.js, files >400KB skipped |
findings marked confidence: low + disclaimer |
| Live dashboard (host.call) | harness lives only in the dynamic-plugin sandbox; unreliable for static plugins | Web hybrid review: static embed + /api/refresh dynamic re-analysis; offline via generate-dashboard.mjs -> build-ui.mjs rebuild |
| Live session-event stats | no runtime event channel for static client plugins | history_stats snapshot trends instead |
Layout
core/— dependency-free engine (semver / composition / truth / graph / conflicts / simulation / visualization / knowledge / calibration / leaks / upgrade)cli/— standalone TUI/Web/check entry (evidence-based mode decision)src/— cordis plugin shell (src/tools/ per-tool modules, 14 tool schemas + registration)ui-plugin/— browser client plugin (sidebar entry + modal dashboard)web/— dashboard client script (embedded at generation time)prompt/— expert persona prompt (with risk prediction)data/— ecosystem snapshots (ecosystem.jsonversioned;history/runtime-generated and gitignored)reports/— generated reports and graphstest/— self-contained test suites (23 suites, 975 items, no machine dependency)scripts/— build and mount scripts
Links
More in this category
yjh051108/dsh-routing-suite★ 7000
One repository, three parts: a runtime injector for DSH plugin packages (inject, hot-reload, unload, promote a dev staging tool to the front, route self-heal, plus a settings-page plugin manager that lists, unloads and drags folders in to internalize), a task-aware reasoning-mode router agent preset (router-standard / router-spec / router-react), and a graded two-level task protocol whose six tools (commit_star, lock_stage, revise_do, edit_plan, mark_task, redteam_verdict) pin task state to disk. The injector implementation ships in-tree, so the install carries its own behaviour rather than a dependency list.
strukto-ai/mirage#dsh★ 3678
Swaps the filesystem and bash providers for a mirage virtual workspace: file tools and shell commands run over mounted resources (RAM, S3, Redis, Slack, Gmail, Notion, Postgres) instead of the host disk, with per-mount read/write/exec modes, per-command sandbox routing (monty, pyodide, quickjs in process; docker, e2b, daytona remote), and installed CLIs (git, gh, slack, linear, ntn, gws, or one you register) as head words in the virtual terminal.
hust-open-atom-club/oh-dsh★ 324
Community distribution: TUI, desktop, and Web UI as one bundle with layered installation.
weijiafu14/pi2dsh★ 212
Pi Host ABI compatibility engine: after one install, unmodified Pi extensions from npm mount as native DSH plugins with `dsh plugin add <pi-package>`. Verified end to end on stock DSH with pi-mcp-adapter (full MCP manager: OAuth, resources, prompts, MCP Apps, elicitation, sampling), @tintinweb/pi-subagents, pi-code, pi-hermes-memory and pi-background-tasks; `pi2dsh inspect` reports a package's compatibility before installing.
Fishquito7/dsh-skill-mcp-panel★ 175
Manages DSH skills and MCP servers from the web settings: skill cards with hot enable/disable, workspace scopes, groups, batch migration and drag-and-drop import, plus stdio/HTTP MCP CRUD with connection tests, secret redaction and the unified dsh-panel CLI.
lire1131/dsh-undo-savepoint★ 172
Undo/redo & rollback system for DSH: every config change is auto-snapshotted; undo/redo/restore to any version from the WebUI or the offline CLI/GUI tools (works even when DSH fails to boot).
Community comments
Comments are public GitHub Discussions. Loading them connects to GitHub and Giscus; a GitHub account is required to post.