dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
A preventive governance plugin for DeepSeek Harness: the cloud planner is denied write and shell access, a local worker implements inside a bounded workspace, and promotion is hash-bound against a machine-checked or operator-attested record. Five boundaries, each failing closed.
Repo-native cryptographic attestation, anti-self-approval enforcement, and an execution perimeter for autonomous coding agents.
Every verified delegation leaves a signed record in the repository's own Git notes, bound to the commit it describes: the execution receipt and the human approval are two signatures made by two different keys, and the audit that checks both runs offline. Control mapping for SOC 2 CC8.1, ISO/IEC 42001 and the EU AI Act: docs/enterprise-governance.md.
Who this is for — the roles that are blocked today, and the obligation each one is trying to discharge: Target audience and market positioning.
A DeepSeek Harness (DSH) plugin that separates who specifies work from who implements it, and refuses to let the first party write the second party's code. It is a technical control, not a policy: enforcement happens in a tool-call hook before a write lands, so it does not depend on the model choosing to comply.
The metered model has no write tool and no shell. A fully prompt-injected architect can plan anything and still cannot change a byte of your host, because the permission is never granted.
Two properties, both of the kind a pipeline usually asserts rather than enforces. Everything else in this README is in service of them.
A record under attestation spec 1.2 carries a worker receipt and a reviewer approval, with three signatures sealed in order: the worker signature over the payload, the reviewer signature over the payload *including* the frozen worker block, and the outer envelope seal last, because adding the reviewer block would invalidate an earlier seal.
self-approval refused. Red-team probe10 signs a reviewer block with the worker's own key; without that check the record verifies perfectly.
resolved trust root does not know is refused (probe 9).
--prepare runs the contract andstages an untracked draft that cannot be committed; --approve --reviewer-identity "" re-verifies the draft against the anchored tree, adds the reviewer block, attaches once, reads the note back byte-identical, and only then removes the draft. It does not re-run the contract: the record must carry what phase one saw, not a second opinion collected later.
delegate_worker settles execution status only — the fourregistry outcomes UNIT_PASSED, UNIT_FAILED, UNIT_UNVERIFIED and UNIT_FLAKY, which are verdicts and not signing keys. The three tool parameters that once let a caller name a reviewing human are gone, and a compile-time assertion keeps them gone.
Residual boundary. With the in-repo reviewer key in use, a committer who can edit both keys/delegation-reviewer.pub and the operator pin could substitute both roots. Pin the reviewer root out of band with DSH_REVIEWER_PUBKEY or DSH_REVIEWER_FINGERPRINT, and a second signature becomes evidence about a principal the record's author cannot reach. Details: dual attestation.
Attestations are Ed25519-signed notes in refs/notes/delegations — objects in the same database as the code, so they clone and verify offline. Every claim in a record is re-derived at audit time from the anchored commit's tree, never from the working copy: a note that names one commit and lives on another, whose anchor is not an ancestor of main, or whose artifact or contract digest does not match the blob at that commit is refused. The full check list is under Cryptographic Provenance & Attestation Model, and is specified in full in docs/enterprise-governance.md §3.
Residual boundary. A Git ref is not write-once storage: notes can be edited, re-attached or removed, and the ref can be force-pushed. The audit catches every mutation that leaves a record behind — the red-team harness performs ten of them — and it refuses an empty ledger, but it cannot detect one note removed while others remain. That needs an external sink, and the auditor says so in its own closing line.
Run these from a clone. The published npm package is the plugin (plugin/dist); the gate and signing tooling deliberately live in the checkout rather than in the tarball, so there is no standalone CLI to install and no extra artefact to trust:
npm run gate # all seven commands (eight tools), offline
node scripts/verify-delegation-ledger.cjs # the ledger audit alone
node scripts/redteam-probe.cjs # ten attack classes; restores the ledger afterwardsA green run prints AUDIT PASSED, then the one limit that matters: *"this proves the records present are sound. It cannot detect a record that was deleted."* To check a published release against its tag — this one needs the network — run powershell -File scripts/verify-release-tarball.ps1 -Version -Tag v, substituting the release you are checking; it compares the tarball and the tag in both directions by Git blob hash.
The same gate runs on every push in .github/workflows/ci.yml, with fetch-depth: 0 and an explicit refs/notes/delegations fetch, because a depth-1 checkout would audit an empty ledger and report success. The v0.5.7 release commit was gated by run 210, which concluded success. A CI workflow holds no signing key, so the signer lifecycle step reports a named # SKIP there rather than passing silently.
dsh-plugin-coding-delegate puts an enforcement boundary between an architect model and an untrusted worker: it intercepts the handoff, keeps the worker from seeing the tests that judge it, sandboxes the verification run, and can sign a cryptographic note per unit.
--permission, which older releases do not have.web, tauri, headless, or your own), with an architect modeland a reachable worker endpoint (local LM Studio at 127.0.0.1:1234, or a cloud worker you choose).
attestationPrivateKeyPath if you want the unit signed. Without onethe verdict is still produced and the attestation is withheld, not faked.
dsh plugin --profile web add dsh-plugin-coding-delegateDSH does not read a plugins array from a config file. A profile is a directory at $DSH_HOME/profiles/ with its own package.json and cordis.patch.yml, and dsh plugin forwards to pnpm inside it. npm install in your project does not mount the tool.
The plugin ships a patch that inserts one entry; DSH applies it when the bundle is loaded. On startup:
[LOCAL_ROUTER_INIT] Tool 'delegate_worker' registered successfully on ctx.tools.If you do not see that line, the active profile is not loading the plugin — check which profile the process booted, not the project you are standing in.
A contract is the oracle for one unit. It must be a standalone script:
// tests/contract-add.cjs — .cjs, because the default package type is CommonJS
const assert = require('node:assert');
const { add } = require('../src/add.js');
try {
assert.strictEqual(add(2, 3), 5, '2 + 3 must equal 5');
assert.strictEqual(add(-1, 1), 0, '-1 + 1 must equal 0');
console.log('CONTRACT_VERIFIED');
process.exit(0);
} catch (error) {
console.error('CONTRACT_FAILED: ' + error.message);
process.exit(1);
}Rules the sandbox enforces, each with the refusal you will see:
rule · refusal direct node only · REFUSED_UNSANDBOXED_RUNNER for node --test no shell chaining or redirection · REFUSED_SHELL_OPERATORS node runtime only · REFUSED_UNSANDBOXED_RUNTIME for python, sh, … the host binary only · REFUSED_SHADOW_RUNTIME for ./node or a temp path exit 0 on pass, non-zero on fail · the verdict is VERIFICATION_FAILED
Use delegate_worker to implement src/add.js, with contractFiles ["tests/contract-add.cjs"]
and the verification command node tests/contract-add.cjs.contractFiles is the declaration the gate trusts. Passing that same path in contextFiles is refused with REFUSED_CONTRACT_AS_CONTEXT — the worker may not be shown the tests it is graded by.
architect dispatches
├─ contract/context segregation, before any file is read REFUSED_CONTRACT_AS_CONTEXT
├─ worker emits fenced blocks
│ └─ test paths refused before the write isTestPath
├─ verification runs: node, --permission, shell:false,
│ prototypes frozen, sockets severed, env scrubbed
├─ verdict from the lattice: boundary > gate > flaky >
│ coherence > unverified > success
└─ attestation when a key is configured: Ed25519 note on
refs/notes/delegations, digest-bound to the commitThe staged-bytes check (git show :) belongs to the promotion gate that runs at commit time, not to the delegation itself — a distinction that matters when you are reading which control caught a change.
profile, not per project.
creation; grant your account full control over the workspace.
--test. Rewrite it as a scriptthat exits 0/1.
contextFiles; declare the interface theworker needs in a separate spec file.
For profile options, custom key paths, environment flags and enterprise wiring, see Install below; this section is the short path to a first verified delegation.
Coding needs two different jobs done, and they want two different contexts. The plugin gives each one its own window and lets exactly two things cross between them.
The architect is the metered thinking model. It holds the design conversation, decides how the work decomposes, and writes a contract for each unit: what to build, where the worker may write, and the command that decides whether the unit passed. It does not write source. Reading it back is governed rather than forbidden: with the default sourceReadEgress: 'source' a read returns the file, rule 3 makes a read of a freshly-delegated one ask first, and sourceReadEgress: 'declarations' serves a type skeleton instead of the body.
The worker is whatever your GPU is already running. It receives one unit and everything that unit needs — nothing else — writes the code, and is discarded. A fresh context per unit costs nothing.
Direction · What crosses · What never crosses architect → worker · the contract: instruction, permitted paths, the verification command · the design conversation, the other units worker → architect · the verdict: pass/fail counts, a redacted failure structure, the names of files written · the code
The verification command is sandboxed, and that is a breaking change in 0.5.11. It runs as a node process under --permission, with filesystem access scoped to the workspace and the OS temp directory, core prototypes frozen, sockets and fetch severed, and the environment scrubbed. What that means for a contract command:
node . The runner form node --test is refused(REFUSED_UNSANDBOXED_RUNNER) because the runner forks a child process per test file, the permission model blocks that fork, and granting it would reopen the execution vector the sandbox closes.
0 on pass, non-zero on failure.python, sh, bash, pwsh and other runtimes are refused(REFUSED_UNSANDBOXED_RUNTIME): the sandbox reaches node processes only, so anything else would run bare while the record claimed isolation.
./node, temp/node.exe and other path-shaped binaries are refused(REFUSED_SHADOW_RUNTIME); the spawn uses the host binary the plugin is already running under.
with shell: false, so there is no intermediate shell to expand or chain anything.
Its raw output stays on the local machine; what travels back is the failure *structure*, with source stripped out.
Status: 0.5.11, published to npm and gated in CI. The mechanisms work and are tested, and their
limits are documented rather than glossed, including several that cannot be closed from inside the
process — see What this control does not cover and the consolidated