DeepSeek Harness plugin

dsh

Skill-driven harness/loop engineering workflow agent plugin.

Jump to install

Source facts

Repository
btspoony/mstar-harness
Latest update
Aug 14, 2026
Category
Workflow & Automation
GitHub stars
49

Install

Start with a prompt that asks an agent to read the source. Switch to the command if you want to install it yourself.

Copy this prompt into DSH, Codex, or another agent and ask it to read the page and repository first.

Do not install anything yet. Read this DeepSeek Harness plugin and explain what it does, which files, networks, or credentials it can access, and how to install and remove it.

Plugin page: https://deepseekplugins.org/plugins/btspoony/mstar-harness~23dsh
GitHub: https://github.com/btspoony/mstar-harness/tree/main/packages/dsh
Plugin: mstar-harness#dsh
Author: btspoony
Install command: dsh plugin --profile web add @mstar-harness/dsh

Do not run the install command until I confirm.

Check the source files

Read the README and other files from this plugin directory before installing.

File explorer2 files
README.mdSource · read only

@mstar-harness/dsh

English | [中文](README.zh.md)

Morning Star as a first-class dsh (DeepSeek Harness) host — a cordis function plugin that mounts the mstar engine in-process, implements the engine HostAdapter (host: 'dsh'), guards {HARNESS_DIR}/status.json writes (validate + advisory; repair-escape under hard), blocks disallowed subagent dispatches when Enforcement: hard is on, lints SKILL.md writes under the mounted skill roots, mounts the mstar skills/ mirror through the dsh skill-filesystem provider (single canonical mount), and appends a durable mstar-engine-status catalog row to every composed agent step. Boot with a dsh Loader app; everything acts through the seam's refusal/advisory channels, never by patching the tools.

Usage

How a dsh app consumes the plugin — install paths, configuration, what mounts at boot, and the enforcement semantics.

Install paths

The package ships as a workspace package (workspaces: ["packages/*"]) with the engine bundled into dist/ at build time (bun run build; dist is gitignored). The install path is the profile bundle, added to the shipped web profile (dsh --profile web — the ready-made web app profile, dsh web), through the dsh.bundle.patch manifest — a patch layer mounted over the dsh-base defaults:

One-command CLI entry (recommended)npx @mstar-harness/cli init --target dsh installs the full capability in one go: it runs the two dsh plugin --profile web add installs below in order (the mstar bundle first, then dsh-llm-fallbacks), and npx @mstar-harness/cli doctor --target dsh reports each plugin row as uninstalled / disabled / mounted. It is the same two-command install, orchestrated; --no-fallbacks skips the second row (and with it the seeded roles — see What you get below).

(a) Registry install (published form) — the npm package carries the built dist/ (no build step on install):

dsh plugin --profile web add @mstar-harness/dsh

(b) Local checkout install (dev) — the package checkout itself, for iterating on the plugin:

cd <repo>/packages/dsh
dsh plugin --profile web add .

dsh plugin --profile <name> add <spec> initializes the profile on first use (web starts from the shipped template: @deepseek-ai/dsh-base + @deepseek-ai/dsh-web-app), forwards <spec> to pnpm in the profile directory, and reconciles the profile's dsh.profile.bundles layer list from the installed state: any dependency whose package.json declares dsh.bundle joins the layer stack. Relative specs (., file:/link:) anchor to the invoking directory, so add . runs from the package checkout; pnpm must be on PATH. A local checkout needs a prior bun run build (the prepare script is intentionally NOT used — the monorepo builds packages explicitly, matching cli/opencode).

(c) Optional capability: dsh-llm-fallbacks (second command) — the role-based subagent configuration capability (see LLM fallbacks integration) is a SEPARATE plugin row and must be installed with its own command:

dsh plugin --profile web add dsh-llm-fallbacks

The two-command install is the contract — folding a dsh-llm-fallbacks row into this bundle's patch is explicitly rejected (roadmap §8.3 F4): the loader has no insert-if-absent semantics, so a same-id insert is a duplicate loader entry id boot failure (the whole dsh session fails to start), and a different-id insert mounts the plugin twice — two apply() runs with split fallback state (per-context state stores, double listeners, config-override lottery) for anyone who also installs the package directly. Layer order is the reconcile append order: dsh-llm-fallbacks lands after dsh-base/llm-retry (its hard ordering requirement) and after the mstar row. Single-command multi-activation is an upstream feature gap (reconcile dedup or insert-if-absent patch semantics), not actionable from this repo.

What you get with zero configuration — with BOTH rows installed (via the CLI entry or the two commands above), the mstar plugin declares the 13 mode: subagent mstar role seeds (derived from the bundled harness-agents/ mirror, project-manager excluded) into the fallbacks taxonomy at boot: each seeded role's persona defaults to its mirror description plus the mandatory role-loading guidance line, the seeded state stays revertible (the fallbacks/revert-seed gateway / the settings rollback button), and the runtime advisory reports missing ids and persona overrides. The seeds mechanism is B4 (delivered iter-20260816-dsh-seeds-bridges) — the installed-deployment e2e (tests/install-e2e.spec.ts) closes the verification loop: a real init --target dsh install into a temp DSH_HOME, booted from the installed artifacts, asserts all 13 ids present in the effective taxonomy with non-empty personas. Not included: model routing, automatch dispatch, or the dsh TUI.

> Fresh-publish age window: pnpm's minimumReleaseAge gate can make a dsh plugin add <spec> range resolution pick an older published version (without the seeds surface) for up to ~24h after a fresh publish — re-run npx @mstar-harness/cli init --target dsh after the window (or pin the version) to converge on the latest surface.

Configuration

| Key | Type | Default | Meaning | | --- | --- | --- | --- | | harnessDir | string | per-session workspace probe (.mstar/.agents/.plans/plans/, from the session workspace root — never the launch cwd) | Explicit harness root; wins over engine probing. Required for repos whose harness root is not a probed name — e.g. this mstar-workflow repo itself uses .harness/ (maintenance root, deliberately NOT probed); the probe starts from the session workspace root (never the launch cwd) and STOPS there — it never walks above the session workspace, so a harness dir above it (e.g. a global ~/.mstar) is never adopted. | | enforcement | 'hard' \| 'soft' | compass, else warn-only | Per-deployment override. Precedence: Config wins; else the Assignment's own Enforcement: hard header flag (dispatch gate only); else the iteration compass frontmatter; else warn-only. Config soft is the ONLY local rollback — an Assignment-level soft does NOT override a hard compass. | | dispatchTools | string[] | ['subagent', 'subagent_fork'] | Delegation tool names the dispatch gate matches — the dsh preset's TWO delegation tools, subagent and its fork sibling subagent_fork (both carry Assignment-shaped { description, prompt } args; a toolName config may rename instances). | | dispatchBinding | string | unset (precheck skipped) | The dispatching agent's own harness role; an Assignment whose Execute as equals it is self-recursion. | | roleMap | Record<string, string> | unset | mstar role id (Execute as) → dsh-llm-fallbacks role id. A taxonomy bridge for logging + future rule-driven interop ONLY — never consulted by the decoration (see LLM fallbacks integration). | | rolePersonas | Record<string, string> | unset (bundled mirror default) | mstar role id (Execute as) → persona text; the role-based subagent decoration's override source — a role-matched subagent/start registers the persona as the child's mstar:role-persona system-prompt section; when unset for a role, the bundled harness-agents/ mirror default is used (see LLM fallbacks integration). | | skillRoots | string[] | unset (no custom-root registration) | Additional skill roots registered with the dsh skill-filesystem provider (customSkillDirs semantics — scanned before user roots). Dev-time: the mirror <repo-root>/skills absolute path. | | bundledSkillDir | string | packaged harness-skills/ mirror (package-relative) | Bundled skill root registered with the dsh skill-filesystem provider (bundledSkillDir semantics — scanned last, trusted). Defaults to the package's OWN harness-skills/ mirror (synced by bundle-assets; gitignored) — package-relative, NOT cwd-anchored. An explicit value wins. | | catalogTtlMs | number | 60000 | Pre-step catalog cache refresh interval (ms): how often the per-workspace unified mstar-engine-status catalog row (watermark + iteration gate + workspace-state digest) re-reads status.json / the compass / the knowledge index. The hot path is a timestamp compare + cache hit between refreshes; a mid-session plan/compass/residual change lands within one interval. | | workflowGate | 'off' \| 'warn' \| 'ask' \| 'hard' | 'warn' | Workflow/ralph gate mode (see Gates → Workflow / ralph gate). off = pass-through with no verdict row; warn = advisory-only; ask = first-seen names route through the approval waterfall (P-c); hard = policy violations veto before any child starts. Default warn changes NO hard behavior — the gate is advisory-only unless the deployment opts into ask/hard. | | workflowNames | string[] | unset | Workflow name allowlist (P-a): meta.name values treated as KNOWN by the gate. Empty or absent ⇒ every name is unknown (documented — the gate is NOT "allow all" by omission). Ralph calls carry no meta.name — P-a never applies to them. |

bundledSkillDir defaults to the package's OWN harness-skills/ mirror (see Skills mount) — an explicit Config value still wins. A relative override remains cwd-anchored (skill-filesystem join() semantics against the dsh process cwd), so deployments overriding the default should pass an absolute path in the profile layer (see bundle/README.md).

Composed row set

The profile bundle composes the following rows — the registry rows come from the @deepseek-ai/dsh-base layer, and this bundle's patch inserts the mstar row over them with neutral defaults (the row set the full-app e2e fixture boots):

- name: '@deepseek-ai/dsh-skill'   # skill registry (ctx.skills) — dsh-base row
- name: '@deepseek-ai/dsh-tools'   # tool registry (ctx.tools) — dsh-base row
- name: '@deepseek-ai/dsh-commands' # command registry (ctx.commands) — dsh-base row
- name: '@mstar-harness/dsh'       # this bundle's patch insert (config: {} — plugin defaults apply)

The registry rows mount before the plugin so ctx.skills / ctx.tools / ctx.commands exist when the mstar gates, seam tools, and bundled commands register.

What the plugin does when mounted

  • Status gatefs/write-intent + fs/edit-intent listeners validate {HARNESS_DIR}/status.json writes (engine validateStatus + per-plan findingsCleanupGate over the pre-write document).
  • Dispatch gate — a tools/pre-execute listener on the delegation tool(s) validates subagent Assignment text through the engine's single composeDispatchGate composition (field gate, anti-recursion precheck, default-branch gate — opencode/omp/CLI parity, so violation codes are identical by construction) plus the dsh lease gate and worktree L1/L2 checks.
  • Skill-authoring lintSKILL.md writes under the configured skill roots run the engine skill-authoring lints (lintFrontmatter + lintFiveQuestion).
  • Seam lintsDESIGN.md / audit-plan / knowledge-doc / roles-dir writes under the harness get their artifact-specific engine lints.
  • Model-facing toolsmstar_sdd_workspace, mstar_sdd_task_brief, mstar_iteration_gate, mstar_design_md_validate, mstar_audit_validate, mstar_compound_validate, mstar_roles_validate register on ctx.tools.
  • Bundled commandsctx.commands registrations for /iteration-start, /iteration-drive, /iteration-loop, /codebase-audit (from the packaged harness-commands/ mirror; each declares a frontmatter input hint so the web client claims /name and waits for the user's follow-up args instead of executing immediately; handlers steer the command body + user args into the receiving agent).
  • Pre-step catalog row — every composed agent step appends ONE unified mstar-engine-status catalog message: the watermark (unified mstar version, harness dir, enforcement), the iteration phase-gate section (when a steering compass resolves) and the workspace-state digest (plan registry, open residuals, branch/policy anchors, active leases, knowledge digest, compass direction — when the workspace has a status.json). The row is digest-gated (injected once per turn, re-injected only when it changed) and shares one TTL-cached per-workspace build (catalogTtlMs, default 60 s).

Enforcement semantics

Warn-only by default: gate violations log and emit advisory events (mstar/status-gate, mstar/dispatch-gate, mstar/skill-lint, seam advisories) and the action proceeds. Enforcement: hard — from the iteration compass frontmatter, the Assignment header, or the plugin Config (enforcement: hard) — escalates violations to a real veto/deny through the cordis refusal channels: subagent dispatch returns PreToolDecision { kind: 'deny', reason } without delegating; status/skill-lint writes are never hard-vetoed because the intent waterfall is content-blind — an already-invalid document is allowed as a repair escape (hard: true, repair: true advisory) so the repairing write can land. Config soft is the only local rollback; hard gates are never a global default.

Gates

Status gate

fs/write-intent + fs/edit-intent listeners (registered prepend so they run before dsh-fs-policy) gate writes to {HARNESS_DIR}/status.json: validateStatus + per-plan findingsCleanupGate over the current on-disk document (parsed exactly once — no TOCTOU double read). The gate never throws: every decision surfaces as the mstar/status-gate advisory and the intent waterfall is delegated via next(). Warn mode (default) logs + emits on violations. Hard mode allows an already-invalid document as a repair escape (error-level log + advisory with hard: true, repair: true) — the intent waterfall carries no incoming content, so a hard veto on an invalid document would deadlock the very write that repairs it. Unexpected internal errors degrade to allow in BOTH modes with a degraded: true advisory (error-containment envelope); the corrupting write itself cannot be vetoed on this seam (see Known Limitations).

Dispatch gate

tools/pre-execute listener on the delegation tool(s): parses the payload's Assignment text and runs the engine's SINGLE dispatch-gate composition (composeDispatchGate — shape guard, validateAssignmentFields, antiRecursionPrecheck, default-branch gate, header-region enforcement; the same composition the opencode/omp/CLI bindings use, so violation codes are identical by construction) over the header region, plus the dsh-side worktree L1/L2 checks and the lease gate. The refusal channel is PreToolDecision { kind: 'deny', reason } returned without calling next(); warn mode logs, emits mstar/dispatch-gate, and delegates. Non-Assignment prompts and non-delegation tools are inert. Engine failures degrade to allow in both modes observably: the catch path emits the plugin-owned advisory with degraded: true + an error log, so a hard deployment can detect a dead control instead of a silent pass. Registered prepend so an earlier-mounted decision can never…

Lease gate

Additive beyond the opencode field set: for writable dispatches whose Assignment declares Execution mode: sdd or whose plan row is InProgress, verifyPlanExecutionLease + dispatch-context comparisons (holder, worktree_path, working_branch) run against {HARNESS_DIR}/status.json. Violations use the dsh-side lease.dispatch.* namespace; read-only roles skip the check entirely. A missing status.json on an sdd dispatch is NOT a silent fail-open: it surfaces lease.dispatch.unverifiable (advisory in warn, deny under hard) — the execution_lease cannot be confirmed without the status file. Non-SDD dispatches keep the degrade-allow (no lease obligation). All Assignment field reads are scoped to the engine assignmentHeaderRegion (body-quoted examples never leak into header fields).

Skill lint gate

fs/write-intent listener scoped to SKILL.md files under the configured skill roots runs the engine skill-authoring lints (lintFrontmatter + lintFiveQuestion — the CLI mstar skill lint combination) on the pre-write on-disk document. The slot is content-blind (the intent waterfall carries only (target, actor)), so: missing file = first create = pass; clean on-disk doc = silent pass; violations in warn mode = advisory + delegate; violations in hard mode = repair escape — the document is ALREADY invalid, so this write may BE the repair (error-level log + hard: true, repair: true advisory with the enforced hardBlocked verdict). Enforcement resolves like the other gates (Config override, else the iteration compass, else warn-only). The gate never throws; read failures and unexpected errors degrade to allow with a degraded: true advisory. The typed hard veto (SkillLintVetoError, code skill-lint.veto) lives on the incoming-document branch (lintSkillWrite) — see Known Limitations for its current wiring.

Workflow / ralph gate

A tools/pre-execute branch (BEFORE the subagent prompt branch) gates the workflow and ralph tool calls — the remaining model-reachable fan-out that carries no Assignment text. It matches the FIXED tool names (workflow / ralph); a renamed workflow instance is out of scope (the name guard is the fixed default). Non-workflow tools are untouched — the subagent branch owns them, semantics unchanged.

Four-tier mode (Config workflowGate, default warn): off (pass-through, no verdict row), warn (advisory-only), ask (first-seen names route through dsh's approval waterfall — {kind:'ask'}, fail-closed upstream; this gate invents no answerer), hard (policy violations veto before any child starts). The policy is the SINGLE decision point — P-b lease attribution runs FIRST and preempts P-a/P-c, then the P-a name allowlist, then P-c first-seen ask.

Policyoffwarn (default)askhard
P-b: workspace has an InProgress plan without execution_lease coverageallow (gate short-circuits off)warn — allowed + advisory (workflow.lease.uncovered) + one warnwarn — allowed + advisory + one warn (the ask channel is for first-seen NAMES, never the workspace red line)deny — veto before any child starts (workflow.lease.uncovered), reason cites the plan id
P-a: workflow name ∈ workflowNames (non-empty list)allow (short-circuit)allow — no advisory (P-a passes under every mode)allow — no askallow
P-a: workflow name unknown (empty/absent list ⇒ every name unknown)allow (short-circuit)warn — allowed + advisory (workflow.name.unknown) + one warnask (first-seen) → {kind:'ask'}; the cached decision (allow/deny) is reused afterwards — never a re-ask for a resolved namedeny — veto before any child starts (workflow.name.unknown), reason names the name
ralph (no meta.name — no allowlist identity)allow (short-circuit)allow — P-a/P-c NEVER applyallow — P-a/P-c NEVER applyallow — P-a/P-c NEVER apply; P-b still applies (deny when uncovered)

Default-warn rationale. warn is the default so the gate never surprises a deployment into a hard block: it is advisory-only unless the operator opts into ask (human ask channel) or hard (veto). An empty/absent workflowNames makes every name unknown — the gate is not "allow all" by omission, but the default mode turns that into an advisory, not a block.

Interaction with Enforcement: hard. The workflow gate's mode is its OWN Config knob — the cross-cutting Enforcement: hard resolution (compass / Assignment header / Config enforcement) does NOT escalate workflowGate. A hard-enforcement deployment still runs the workflow gate in