btspoony/mstar-harness--packages-dsh ↗★ 58
@mstar-harness/dsh
提供进程内引擎状态调度与硬拒绝通道控制
AI 分析
适合需要对DSH引擎进行状态分发和租约管理的系统级任务。
安裝
npx -p @deepseek-ai/dsh dsh plugin --profile web add github:btspoony/mstar-harness#cd811d651df342990fb6d6f06ced424be3ee4b47&path:packages/dsh說明文件
閱讀完整 README ↗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 / drifted (drifted = the fallbacks row is installed at a version other than the pinned one; init --target dsh re-adds the pin, doctor exits non-zero until then). 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 /packages/dsh
dsh plugin --profile web add .
dsh plugin --profile add initializes the profile on first use (web starts from the shipped template: @deepseek-ai/dsh-base + @deepseek-ai/dsh-web-app), forwards `` 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 — 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
minimumReleaseAgegate can make adsh plugin addrange resolution pick an older published version (without the seeds surface) for up to ~24h after a fresh publish — re-runnpx @mstar-harness/cli init --target dshafter the window (or pin the version) to converge on the latest surface.
Headless profile (one-shot runs)
The plugin is not web-bound: it also mounts in the dsh headless profile (dsh --profile headless "" — the one-shot, no-GUI/no-port mode). The install path is identical, one command:
dsh plugin --profile headless add @mstar-harness/dsh
The shipped headless template auto-initializes on first use (@deepseek-ai/dsh-base + @deepseek-ai/dsh-headless), and the reconcile step appends the mstar row to the bundle stack (dsh-base → dsh-headless → @mstar-harness/dsh). Every plugin capability rides a dsh-base seam that headless inherits — status/dispatch/lease/worktree gates, the skill mount, the engine-status catalog, the harness-rules system-prompt injection, the 7 model-facing tools — so the harness is fully live in a one-shot run. Launch from the repo working directory (the runner writes meta.cwd = process.cwd() and the per-workspace harness-dir probe starts there). The browser client half is web-profile-only and simply does not load.
Headless usage caveats (dsh 0.1.0-rc.6 verified):
- One-shot turn model — the runner submits the task as one user message and exits when the agent goes idle (
whenIdle()); it does NOT awaitrun_in_backgroundchildren. Foreground subagent dispatch works (a child session is created and its result reaches the parent); background QC-tri-style parallelism does NOT complete in-process — either dispatch QC seats foreground (serial wall time) or have the agent collect background results withtool-subagent-controlBEFORE ending the turn. - No interaction channel —
ask_user_questionand approval prompts fail closed (there is no answerer). UseDSH_PERMISSION_MODE=danger-full-accessfor unattended runs (sandboxdanger-full-access+ approvalnever); interactive Prepare flows (grill-me) belong on the web profile. - Default model resolution — headless composes no fallbacks row, so an
agent-default-modelsettings pin ofFallbacksChainfails withNO_ADAPTER(the web-profile artifact). Point the default model at a real provider, or installdsh-llm-fallbacksinto the headless profile too (note: on the published dsh 0.1.0-rc.6 the fallbacks settings integration predates theSettingsProvider.installSectionAPI, so the virtual adapter does not register — this resolves with dsh ≥ 0.1.2-alpha). - Config via the profile user layer — profile-level
cordis.patch.ymloverrides work as documented (e.g.enforcement: hard+dispatchBindingon the mstar row); the mstar row's ownconfig: {}stays neutral.
Configuration
| Key | Type | Default | Meaning |
|---|---|---|---|
harnessDir | string | repo .mstarc [config] harness_dir, else 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; 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 repo .mstarc [config] enforcement; else the iteration compass frontmatter; else warn-only. Config / .mstarc soft are the ONLY local rollbacks — 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 → fail-closed empty-binding under hard | The dispatching agent's own harness role (the anti-recursion CALLER); an Assignment whose Execute as equals it is self-recursion. |
roleMap | Record | 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 persona channel (see LLM fallbacks integration). |
rolePersonas | Record | unset (bundled mirror default) | mstar role id (Execute as) → persona text; the native subagent persona channel's override source — a role-matched start (one-shot start or the opt-in continuable startContinuable) merges the persona into the native request persona slot (the child embodies the role persona INSTEAD OF the deployment persona; persisted + reapplied on resume). Merge order: the request's own persona wins AS-IS (a caller-set persona is never overridden — no role merge); otherwise a non-empty entry beats the bundled harness-agents/ mirror default, an empty-string entry is treated as unset and falls through to the mirror default, and an absent entry uses the mirror default (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 /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 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. Recommended for the mstar read-only fan-out path: ['mstar-qc-tri', 'mstar-audit-fanout', 'mstar-pr-seats']. |
Recommended operator overlay. The three recommended workflowNames above cover the mstar read-only fan-out path (plan QC tri, large-repo /codebase-audit, /amazing-pr-review deep); listing them is an operator overlay in the profile layer, never an mstar default. With the shipped empty list every name is unknown, which under the default workflowGate: 'warn' is one workflow.name.unknown advisory the run survives. A production deployment that also wants unknown names vetoed sets workflowGate: 'hard'; the shipped default stays 'warn'.
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 gate —
fs/write-intent+fs/edit-intentlisteners validate the v3 coordination-document target set — the v2 root{HARNESS_DIR}/status.json,workflows//snapshot.jsonandprojects//residuals.json— each with its matching engine validator (validateStatus= v2 root /validateWorkflowSnapshot/validateProjectRegister, the P2-fixedharnessDocKindOfTargetshape), plus the snapshot-targetfindingsCleanupGateextension per plan row that configures a mode (residuals read from the project registers). - Dispatch gate — a
tools/pre-executelistener on the delegation tool(s) validates subagent Assignment text through the engine's singlecomposeDispatchGatecomposition (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 lint —
SKILL.mdwrites under the configured skill roots run the engine skill-authoring lints (lintFrontmatter+lintFiveQuestion). - Seam lints —
DESIGN.md/ audit-plan / knowledge-doc / roles-dir writes under the harness get their artifact-specific engine lints. - Model-facing tools —
mstar_sdd_workspace,mstar_sdd_task_brief,mstar_iteration_gate,mstar_design_md_validate,mstar_audit_validate,mstar_compound_validate,mstar_roles_validateregister onctx.tools. Themstar_iteration_gatemirror takes the v3 inputsnapshot_path({HARNESS_DIR}/workflows//snapshot.json— mirror ofmstar iteration gate --workflow; the oldstatus_pathroot input is gone with the v1 read path). - Bundled commands —
ctx.commandsregistrations for/iteration-start,/iteration-drive,/iteration-loop,/codebase-audit(from the packagedharness-commands/mirror; each declares a frontmatterinputhint so the web client claims/nameand 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-enginecatalog 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 astatus.json). The row is digest-gated (injected once per turn, re-injected only when it changed) and shares one TTL-cached per-works