Repository navigation
Releases: jjmlovesgit/dsh-plugin-coding-delegate
Release list
v0.5.12
Full Changelog: v0.5.11...v0.5.12
v0.5.11
Release v0.5.11
⚠ BREAKING: verification commands are now sandboxed
A verification command no longer runs as an ordinary subprocess. It runs as a node process under Node 22
--permission, with filesystem access scoped to the workspace and the OS temp directory, core
prototypes frozen, sockets and fetch severed, the environment scrubbed, and no shell — the command
is tokenised and spawned with shell: false against the host's own node binary.
What that means for a contract command:
- Prohibited:
node --testandnode -t— refused withREFUSED_UNSANDBOXED_RUNNER. 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. - Prohibited: relative or shadow binaries (
./node,temp/node.exe) — refused with
REFUSED_SHADOW_RUNTIME. The spawn always usesprocess.execPath. - Prohibited: shell chaining and redirection (
&&,;,|,>,<, backticks,$() — refused
withREFUSED_SHELL_OPERATORS. - Prohibited: non-node runtimes (
python,sh,bash,pwsh) — refused with
REFUSED_UNSANDBOXED_RUNTIME. The sandbox reaches node processes only. - Required: run the contract directly as
node <script>, assert its invariants, and exit0on pass
or non-zero on failure.
If your verification command was node --test tests/…, it will fail on first run after upgrading. The
refusal names the direct form of your own command.
Security and hardening
- Execution boundary. Verification is pinned to
process.execPath; the preflight freezesObject,
ArrayandFunctionprototypes, seversnet.Socket.prototype.connectandfetch, and removes
non-essential environment variables. Measured against four hostile leaves that all executed before this
release. - Role and attestation integrity. A delegation whose
contextFilesinclude its declared contracts is
refused before dispatch (REFUSED_CONTRACT_AS_CONTEXT). The promotion gate reads staged index bytes
(git show :<path>) instead of the working tree, and fails closed whengit difffails. - Egress and DLP. The outbound scanner now covers tool results — every role, nested
outputblocks,
stdoutand serialised objects — not just prompt text. Declarations mode is an allowlist:.d.ts,
mappable source served as its declaration, and prose; raw.py,.sh,.jsonand.yamlreads are
refused (REFUSED_NON_DECLARATION_READ), and glob reads are refused (REFUSED_WILDCARD_READ).
Compatibility
The tool surface, verdict vocabulary and attestation schema are unchanged. The breaking item is the
verification command contract above.
Full Changelog: v0.5.10...v0.5.11
v0.5.10-arch-lock
v0.5.10
v0.5.9
v0.5.8
v0.2.0 - Enforced local-hybrid governance plane
A control release, not a savings release
v0.2.0 is the release in which this plugin stopped claiming a token or privacy benefit and became an enforced governance control. The metered model specifies and is denied write and shell access; a local worker implements inside a workspace-bounded directory; a verdict — never code — crosses back. Promotion accepts a file only when its bytes hash-match a machine-checked or operator-attested record.
Metadata note: this tag points at 8f8f923. It was originally created at f532e0c, which was seven commits behind the version metadata it named — at that commit plugin/package.json still declared 0.1.0. It has been moved forward so the tagged tree is internally consistent.
Release metadata
0b32f04— aligned the version metadata with v0.2.0:plugin/package.json, its lockfile and the README all said0.1.0while the tag saidv0.2.0. They now agree.61afc66— rewrote the package description, which still sold the retired cost-and-privacy premise. It now describes the boundaries and the hash-bound promotion gate.
Behaviour fix — a refusal that pointed at an impossible remedy
1057885— the missing-skeleton branch told every caller to "build the declarations", which is right forsrc/and unachievable fortests/:tsconfig.jsonsetsrootDir: ./srcandinclude: [src/**/*], so a test file sits outside the emit root and no build will ever produce its.d.ts. A reader following the instruction looped. The branch now discriminates betweentests/andsrc/, verified against seven paths including the near-missessrc/latest.tsandcontest/a.ts.
Packaging fix — a bare import that only resolved by accident
02701fb—src/index.tsimported from the bare namecordis, which resolved only because it is a transitive dependency of@deepseek-ai/cordis. That is the failure mode the framework's dependency-scoping rule exists to prevent: it works on the author's machine and breaks for every consumer. Nowimport type { Context } from '@deepseek-ai/cordis'. Removing the bare dependency took 16 transitive packages with it — 95 to 79 undernpm ci. Every scoped import in the plugin is now type-only and audited.
Documentation — the retired claims, corrected rather than deleted
d45b7ce,c2c0d7d,8f8f923— three rounds of correction. Retired cost and privacy claims are recorded as retired in Retired claims, and why, anddocs/control-effectiveness.mdnow states plainly what the control does not cover.
Two operational limits were codified, both found by operating the thing rather than reasoning about it:
- Egress policy is session-scoped.
sourceReadEgressis read once at registration from the profile patch, so changing it is a restart rather than a setting. As shipped the key is unset — the option, the hook and its oracle all exist, and the control is currently off. - The contract files the architect may write are the ones it cannot read back. The write guard's contract carve-out is reached before its extension check, so
tests/is writable undercontractWriteMode: 'allow'; nothing undertests/emits a declaration, so the same file is unreadable underdeclarationsmode.
Corrections to previously published reasoning
Two claims in earlier revisions of docs/control-effectiveness.md were false, and both are corrected in place with the retraction preserved:
- That
sourceReadEgresshad been verified to reload live. It had not — the option never applied, and the earlier observation was an artifact of an approval prompt in a different session. - That
scripts/check-promotion.cjshad no oracle because the write guard refuses.cjs. The oracle exists, and a.cjstest undertests/was never refused — the contract carve-out short-circuits before the extension rule. Direct probe of the built guard:tests/oracles/thing.oracle.cjsallow→ permitted,deny→ denied, whilescripts/check-promotion.cjsandlib/util.cjsare denied as ordinary source.
Verified state at this tag
- Build clean; committed
distmatches a clean build. - 39/39 unit tests, 356/356 regression oracles.
- Three
.mjsoracles: promotion socket 12/12, attestation identity 6/6, tool surface 5/5. - README consistency check green (8 policy rules).
- CI: run 37962806250, all 11 steps
successon Windows.
Scope, stated honestly
This release claims no token, cost, session-length or privacy benefit. Measured: the delegation path saved roughly $0.15 on a $10.63/month bill. The value is the control — a file ships only against a hash-bound record — and the limits are documented: the recorder shares a process with the recorded, the guard sees tool calls rather than intent, and OPERATOR_ATTESTED is tamper-evidence rather than cryptographic non-repudiation.