Upstream compatibility
September 20, 2026 · View on GitHub
Verification date: 2026-09-19 (DSH, TypeSafe, Node). @buberlo/* npm
versions re-checked with npm view on 2026-09-20: registry 0.1.0 only.
Everything below was checked against the sources named here, not against
examples copied from earlier discussions.
Versions and sources
| Source | Version / commit | How it was obtained |
|---|---|---|
deepseek-ai/deepseek-harness | commit ddefc45fbc7f8e46dd73185e68295696d1297887 (2026-09-17), root version 0.1.6-alpha.2 | git clone --depth 1 into a temporary directory |
@deepseek-ai/dsh-* npm packages | 0.1.6-alpha.2 (published; dsh-tools also carries latest: 0.0.1-rc.1) | npm view + installs |
@deepseek-ai/dsh (product CLI) | 0.1.6-alpha.2 | npm install into a temporary directory |
@deepseek-ai/cordis | 4.0.2 | npm |
@deepseek-ai/schemastery | 3.18.2 | npm |
@typesafe-ai/sdk | 0.6.0 | npm + published src/types.ts, src/client.ts, src/questions.ts at tag v0.6.0 |
@buberlo/jev-core / @buberlo/dsh-jev | npm 0.1.0 only (2026-09-19). Workspace 0.1.2 (unpublished: package READMEs + call-scoped assessment wording). No 0.1.1 on the registry. | npm view 2026-09-20 + package.json |
| TypeSafe docs | docs.typesafe.ai (llms.txt, primitives, confidence, models, cookbooks) | fetched |
| Node.js | tested with 26.9.0; DSH engines require `^22.19.0 | |
| pnpm | 12.4.2 | local |
All DSH packages named below are published and externally installable at
0.1.6-alpha.2; no private workspace package is assumed. Each direct
dependency is pinned to an exact version and pnpm-lock.yaml is committed.
Externally verified interfaces
The file references are from the cloned DSH source at the commit above.
Plugin shape and injection
- A Cordis plugin is
export default class ... extends Servicewithstatic injectandstatic Config(schemastery) —packages/core/tools/src/index.ts:789-830. - Services are accessed through a context and are
this-rebound to the accessing context; private#fields do not survive the Cordis service proxy (the getter runs with a derived object asthis). The plugin uses TypeScriptprivatefields for this reason (found by an integration test failure, not by reading). - The bundle/profile install path is
dsh.bundle.patchinpackage.jsonplus acordis.patch.ymlrow (docs/user/develop/basic/publish.md,docs/cookbook/adding-a-package.md).
Tool lifecycle (the MVP extension points)
tools/pre-executewaterfall:(exec: ToolExecution, next) => Promise<PreToolDecision>—packages/core/tools/src/index.ts:146; decision type at:589(allow | deny{reason,info?} | cancel | ask{reason?}).tools/resultobserve-only emit:packages/core/tools/src/index.ts:191; result is deep-frozen; listener failures contained (used for loop counting).ctx.tools.restrict(filter)requires a scoped context (agent.ctx) and fails on empty filters, unknown global names, scope-local names, and the reservedrun_codetransport —packages/core/tools/src/index.ts:1077-1104. Restrictions intersect and never affect scoped registrations.ctx.tools.guard(guard)is synchronous and monotonic; no guard can turn a denial back into permission —packages/core/tools/src/index.ts:1116-1122.ctx.tools.get(name, scope)/ctx.tools.schemas(scope)expose the scope's visible set; a global-only lookup (get(name)with no scope) is how the adapter filters names thatrestrict()may legally mention —packages/core/tools/src/index.ts:1210,:1240.- The pipeline order is fixed: pre-execute → guards → execute → post-execute →
finalizeContent → result (
packages/core/tools/README.md). tools/pre-executecannot rewrite arguments (upstream limitation,packages/core/tools/README.md"Known Limitations"), so approval binding relies on per-call assessment instead of argument rewriting.
Agent scope, lifecycle, and model config
agent.ctxis the agent-scoped context (packages/core/agent/src/runtime-types.ts:174); the loop mints it withcreateScope(loopCtx, agent)(packages/core/agent-loop/src/agent.ts:104).agent/pre-stepwaterfall receives{ agent, messages, turn, step, signal }—packages/core/agent/src/runtime-types.ts:320.agent/requestwaterfall receives{ agent, turn, step, signal }and itsnext()returns anLlmCallConfigthat may be replaced (packages/core/agent/src/runtime-types.ts:337,packages/llm/llm/src/call-config.ts:23). This is the verified mechanism for model routing.agent.inject(UserMessage)queues model-facing context for a later step (packages/core/agent/src/runtime-types.ts:241) — used for the bounded skill hint.agent/disposedis the teardown notification (packages/core/agent/src/runtime-types.ts:270).
Settings and the web client
- Host settings:
ctx.settings.installSection(owner, ns, schema, entry, hooks)registers a namespace whose resolved value layers over the plugin's composed entry;setSource/onChangefire on attach, detach, and every committed change (packages/settings/settings/src/index.ts:472-496). Writes go throughsettings.update(ns, patch)/replace/mutate, anddescribe({ redactSecrets: true })stripsrole('secret')fields (packages/settings/settings/README.md). - Client settings:
ctx.settingsScope.bind({ namespace })returns a revision-fencedSettingsScopewithgetSnapshot,subscribe,set,unset, andmutate(@deepseek-ai/dsh-client-ui-settings/client). - Plugins page slots (
@deepseek-ai/dsh-client-ui-plugin-manager/client):plugins.bundle.configis keyed by the bundle package name and rendered on the bundle's page with{ view: 'page' };plugins.itemis a list occupied by the in-box host-plane pages;plugins.row.configis keyed by<package>#<row id>. - Client artifacts: the module system serves each enabled Loader row's built
./clientexport as a CJS closure factory forwindow.__ModuleLoader__.load({ id, factory });reactandreact/jsx-runtimeresolve through the injected require (baselinePLATFORM_MODULES), and cross-plugin value imports are rejected by the bundle-purity gate (packages/client/tsdown.client.ts,packages/client/web/src/platform.ts). Upstream publishes no tsdown preset for out-of-tree client plugins, so this package reproduces the artifact contract in its owntsdown.config.ts(verified by the packaging test evaluating the artifact). - Limitation found: the published
@deepseek-ai/dsh-client-test-runtime@0.1.6-alpha.2imports@deepseek-ai/dsh-client-ui-renderer/src/client/bind.tsand.../scoped-slots.tsx, but the published renderer ships onlylib/(itsfileslist excludessrc). The slot test bench therefore cannot load from npm at this version; the browser tests exerciseapply()against a recording fake context and render the real component directly instead.
Approval and skills
askruns only after the approval service returnsallowed-onceand fails closed when no answerer is composed (packages/interaction/user-approval/README.md);approval/requestis a waterfall, and an approval is per request. This is the verified approval mechanism; no local approval cache exists.ctx.skills.list({ scope })returnsSkillSummarymetadata, andisModelInvocable(skill)honors the invocation policy (packages/skill/skill/src/index.ts:470,:126).- Local skill discovery (
@deepseek-ai/dsh-skill-filesystem@0.1.6-alpha.2): roots are scanned in rank order —project-dshat<projectRoot>/.dsh/skills(100),project-agentsat<projectRoot>/.agents/skills(200),customSkillDirs(300), user roots (400/500); the project root is the nearest.gitancestor; discovery is one level deep (<name>/SKILL.mdor<name>.md). - Frontmatter contract verified in
skill-filesystem/src/index.ts(parseSkillFile):name(kebab-case) anddescriptionare required,whenToUse,metadata, and the invocation booleans are optional, and unknown keys such aslicenseare ignored. A malformed entry is skipped with a warning and disappears from the catalog. - The standard
@deepseek-ai/dsh-basebundle already mounts@deepseek-ai/dsh-skill,@deepseek-ai/dsh-skill-filesystem,@deepseek-ai/dsh-skill-badge, and@deepseek-ai/dsh-tool-skill(packages/bundle/base/cordis.patch.yml:280-291), so a checked-in.agents/skillsdirectory needs no configuration. This repository vendors the TypeSafe skill there (pinnedtypesafe-ai/skills@65a39f3, seedocs/skills.md), andpackages/dsh-jev/tests/skill-install.spec.tsproves discovery and routing against the real provider.
TypeSafe Jev (System One)
- SDK:
new TypeSafeClient(config),client.systemOne(request, options)with{ state, questions, model }and options{ signal, timeout, retry, headers }(@typesafe-ai/sdk@0.6.0src/client.ts). - Reply:
{ model, answers, usage }; the SDK's own retry policy defaults tomaxRetries: 2, per-attempt timeout 10 000 ms, and the SDK redacts known credential headers but not bodies atdebug. The plugin therefore defaults the SDK log level tooffand does not add a second retry loop. - Primitives and answer shapes (
src/types.ts, docs):- Choice:
{ type:'choice', choice, confidence, probabilities }; option map in the request; documented limit 255 options. - Score:
{ type:'score', score, confidence, legend, probabilities }; probabilities keyed by level index; 2–10 levels;scoreis a probability-weighted mean that may fall between levels. - Noul:
{ type:'noul', noul }— no confidence field; the core never synthesizes one.
- Choice:
- Documented model limits: 64k context per request, 32k for
stateplus the longest question; aliasesjev-latest/jev-preview(currently bothjev-1.13.0). validateQuestionsrejects empty question maps and score criteria that are not a list of at least two entries (SDKsrc/questions.ts).
Installation path that was actually executed
Reproducible registry proof (2026-09-19) plus local proof (see also
scripts/packaging-test.mjs):
pnpm build, thenpnpm packboth packages.- Fresh consumer project:
npm install <core.tgz> <dsh-jev.tgz> <pinned DSH peers>→ plugin loads, fails closed, and resolves the consumer's Cordis instance (no second runtime bundled). tsc --noEmitagainst the installed declarations → clean.- Real product CLI:
npm install @deepseek-ai/dsh@0.1.6-alpha.2, profile created with--from-default-profile headless, our tarballs placed in the profile and the bundle name added todsh.profile.bundles.dsh --profile <name> --dump-configprints the# == @buberlo/dsh-jevlayer with thejevrow.- Booting with a
live-without-key patch fails throughcordis-plugin-loaderwith our exact config error, proving the real loader instantiatedJevRuntime. - Booting with valid config reaches the LLM credential/authentication stage, i.e. the tree (including this plugin) mounted.
Web client served proof (2026-09-19)
A web profile was created from the shipped @deepseek-ai/dsh-web-app bundle,
this repository's tarballs were placed in its dependency tree, and the bundle
was added to dsh.profile.bundles. Booting dsh --profile <name> --no-open
served the application, and the boot HTML listed
@buberlo/dsh-jev/client.js among the client modules. Fetching the composed
module bundle returned our module verbatim:
window.__ModuleLoader__.load({ id: "@buberlo/dsh-jev", factory: (require) => { ... } })
The served module also contains the settings.jev and
plugins.bundle.config strings, i.e. the page the card registers into.
Demonstrated restrictions
- Published on npm at
0.1.0only:@buberlo/jev-coreand@buberlo/dsh-jev(2026-09-19). Verified end to end from the registry:dsh plugin add @buberlo/dsh-jevinstalled both packages transitively into a fresh profile,--dump-configcomposed the bundle layer, a headless boot loaded the host plugin, and a running web profile served@buberlo/dsh-jev/client.js. There is no0.1.1on the registry. Local0.1.1was a README-only bump that was never published. Workspace0.1.2(call-scoped assessment questions that stop read false positives) is not on npm yet. Future releases are manual (docs/publishing.md). - PTC / code mode:
run_codesub-dispatches traverse the same pipeline and are assessed (tested with a nested dispatch), but a full PTC runtime was not mounted here;mode: ptcwould additionally require@deepseek-ai/dsh-ptc-runtime-nodeor equivalent. - Model catalog is advisory:
ctx.llm.listModels()is documented as advisory and does not validate routing, so the adapter treats absence from the catalog as "not verified" and falls back to the existing model. A route is never invented. - Live run recorded (2026-09-19,
jev-1.13.0): first dataset 15/15 fixture agreement, 0 errors, mean 528 ms; after growth, 25/25 (seedocs/evaluation.md). Reproducible with an explicit key; without one the runner reports not executed, never a pass. - Client live counters are blocked upstream at this version: the web
client's Remote capability set is fixed by build-time value imports
(
packages/api/remotes/README.md: "the capability set is fixed by explicit build-time value imports; the Client does not discover the Host's active Services or Remote definitions at runtime"), so an out-of-tree plugin cannot add actx.remote.<namespace>status method. The card therefore shows configured state; live decision outcomes are visible where they already surface — in the session's tool results ([jev] <rule>). - Published client test runtime unusable from npm: both
0.1.5-rc.2and0.1.6-alpha.2import@deepseek-ai/dsh-client-ui-renderer/src/client/bind.ts(andscoped-slots.tsx) while the published renderer ships onlylib/, so the slot bench cannot load from the registry. Browser tests exerciseapply()and the component directly instead. - Approval requires an open turn upstream; assessments only run inside the tool pipeline, so this is satisfied by construction.