dsh-jev
> [!WARNING]
> Development of dsh-jev has been discontinued (October 2026).
> There will be no further releases of @buberlo/dsh-jev or @buberlo/jev-core;
> 0.1.4 is the last version. The code was only ever tested against
> DeepSeek Harness 0.1.6-alpha.x (verified on 0.1.6-alpha.2) and may not work
> with newer DSH releases. Issues and pull requests will no longer be worked on.
>
> For Jev in DeepSeek Harness or any MCP host, please use
> jevcore by PerryLink. It is maintained,
> more widely used, offline by default, and Apache-2.0 licensed:
> jevcore (harness-independent core), jevcore-dsh (DSH plugin) and
> jevcore-mcp (MCP stdio server).
Ideas others are welcome to adopt
This repository stays available under the MIT licence. If any of these ideas are
useful to you, please take them — in jevcore or anywhere else:
- Monotone permission narrowing. Jev may only restrict, never widen:
tool selection intersects with existing restrictions, and call assessments
compose asdeny > hold > ask > allowafter callingnext(), so later
policies are never skipped. Errors, timeouts and stale snapshots fail closed
(ask/hold, neverallow).
Seedocs/policy.md. - Shadow mode and an offline mock as the default.
provider: mock+
mode: shadowlogs decisions without changing behaviour, so operators can
observe before enforcing. - Measured benchmarks and regression sets. Versioned evaluation fixtures,
an on-prem support assessment regression set, and with/without-Jev
benchmarks (e.g. a protected audit trail blocked in 10/10 runs) with method
and limits documented indocs/benchmark.mdand
docs/evaluation.md.
Thank you
Thanks to everyone who tried dsh-jev, reported problems, or contributed —
in particular @Daltonganger and
@autox-my for their pull requests — and to
PerryLink for building and maintaining jevcore.
The original README follows for reference.
The Jev decision layer for DeepSeek Harness (DSH).
DSH runs the agent. TypeSafe Jev makes the small,
fast decisions. Your code decides what the answers mean.
Watch the 66-second Kubernetes troubleshooting demo: healthy pods, broken connections after a
rollout. The agent traces Ingress → Service → pods and repairs the network path.
Jev's site policy gates a broad “allow all traffic” shortcut, so the portal can
recover while PostgreSQL stays isolated. The same freshly recorded model calls
run through both harnesses against a real, disposable Kubernetes cluster, with
live Jev assessments. Clearly labeled replay with neural narration; no live
replanning in this comparison.
Video · Captions ·
Method, all runs and limits.
The replay also shows one harmless reset being blocked—a documented false positive.
user task
│
▼
┌───────────────────────────────────────────────────────────┐
│ DeepSeek Harness agent loop │
│ planning · tools · execution · sessions │
│ │
│ pre-step ──▶ Jev: which tools are relevant? → restrict│
│ tool call ──▶ Jev: is this call safe to run? → ask/hold│
│ result ─────▶ deterministic loop guard (no model) │
│ request ────▶ Jev: which model route fits? → route │
└───────────────────────────────────────────────────────────┘
│
▼
TypeSafe Jev (System One) ← choice · score · noul
No Jev call is planned by the LLM, no model output becomes an explanation, and
no model answer can widen a permission. Jev only ever narrows or gates.
At a glance
| Packages | @buberlo/jev-core (harness-independent) · @buberlo/dsh-jev (DSH plugin/bundle) |
| npm | npm view 2026-09-23 lists 0.1.0, 0.1.2, 0.1.3, and 0.1.4. Dist-tag latest is 0.1.4 for both packages. Workspace is 0.1.4. npm install @buberlo/[email protected] resolves @buberlo/jev-core@^0.1.4. Do not install @buberlo/[email protected] or @0.1.3 (literal workspace:^, EUNSUPPORTEDPROTOCOL). 0.1.3 was abandoned after a staged-version conflict (E409). |
| Verified DSH | 0.1.6-alpha.2 (commit ddefc45), @deepseek-ai/cordis 4.0.2 |
| Verified TypeSafe SDK | @typesafe-ai/sdk 0.6.0 |
| Defaults | provider: mock, mode: shadow — offline, no behavior change |
| Tests | 147 (85 core + 62 DSH integration) · 25 evaluation fixtures plus the on-prem support set |
| Live API | implemented, requires an explicit key; not part of any default |
| License | MIT |
What this is — and is not
Is: a plugin that binds Jev to real DSH extension points, plus a reusable
decision core you can embed in any application (games, search, MCP routers).
Is not: a Jev training or hosting project, a DSH fork, a dashboard, a
database, or an MCP platform. It never auto-applies a model suggestion, never
caches approvals, and never sends repositories, logs, or transcripts by
default.
Try it in 60 seconds
Everything below runs offline with synthetic answers. No key, no network.
git clone https://github.com/buberlo/dsh-jev
cd dsh-jev
pnpm install
pnpm build
pnpm example:coding # tool selection + call assessment
pnpm example:dsh # real DSH services + real plugin (still synthetic)
pnpm example:ops # read-only incident router
pnpm example:game # standalone game, imports only jev-core
What pnpm example:coding shows (excerpt):
=== 1. Dynamic tool selection ===
input task : Fix the failing billing test: read src/billing.test.ts and run the test suite
categories (independent relevance questions):
- files relevance=0.97 relevant=true, pick=read_file p=0.88 conf=0.88
- tests relevance=0.93 relevant=true, pick=run_tests p=0.91 conf=0.91
selected : read_file, run_tests
=== 2. Pre-execution assessment (proposed model call) ===
policy : allow (applied=true)
values : matches=0.96 missing=0.06 violates=0.04
pnpm example:dsh goes further: it mounts the real DSH tool pipeline and
the actual plugin, then shows a call being held with the policy rule that
caused it. Every model value is visibly synthetic (mock/jev-synthetic).
What Jev decides here
| DSH moment | Jev question (example) | Deterministic consequence |
|---|---|---|
agent/pre-step |
Is a tool from category "files" relevant? | narrow the visible tools via scoped tools.restrict |
tools/pre-execute |
Does this specific call match the task? Does it need missing information? Does the call itself violate a stated restriction? (observe ≠ modify) |
allow · ask (approval) · hold · deny |
agent/request |
Which configured route fits this task? | switch provider/model only if the target is verified available |
ctx.skills |
Does this turn need a skill? Which one? | inject one bounded hint; the body loads only if the model asks |
Jev answers three question types; the core keeps their meanings distinct:
| Primitive | Meaning | What code does with it |
|---|---|---|
| Choice | one of a defined set, plus a full probability distribution and confidence | compare probabilities against thresholds, or branch on the selected label |
| Score | an ordinal position on named levels (can fall between levels) | weigh/rank; never shown as a "risk percentage" |
| Noul | probability that a yes/no statement holds (no confidence field) | threshold into a boolean decision |
Independent questions are sent in one request (they cannot see each other's
answers), so the code sends every question it might need and ignores the rest.
Modes and providers
Two independent switches — where answers come from, and whether they may act:
| Mode | Jev requests | Behavior change | Typical use |
|---|---|---|---|
off |
none | none | kill switch |
shadow |
yes | none (decisions are logged) | observe before enforcing |
enforce |
yes | decisions are applied | production |
| Provider | Network | Answers |
|---|---|---|
mock |
none | deterministic synthetic scenarios (default) |
live |
TypeSafe API | real Jev; requires an explicit apiKey |
Start with the default mock + shadow, watch the logs, then move to
enforce, then to live if you want real Jev answers. live + shadow still
transmits state to TypeSafe — it only skips applying the decisions.
Use cases
- Coding assistant — keep only the tools a task needs, gate risky calls
before they run, stop identical retry loops.
examples/coding - Read-only ops router — route an incident to diagnostics while a hard
policy keeps remediation out of reach.examples/ops-readonly - Interactive apps and games — map free text onto a bounded action set with
deterministic consequences, without a chat model.
examples/standalone-game - Any agent harness — the core is harness-independent; the LangChain team
describes the same pattern withTypeSafeClassifier, model routing, and
tool-risk gating middleware (seedocs/architecture.md).
Details and design notes: docs/use-cases.md.
Install into a DSH profile
Current registry release is 0.1.4 (latest for both packages, npm view
2026-09-23). npm install @buberlo/[email protected] succeeds and pulls
@buberlo/[email protected] (^0.1.4, rewritten by pnpm). The full DSH profile
boot was verified for 0.1.0 on 2026-09-19 and has not been repeated for
0.1.4.
dsh plugin --profile add @buberlo/[email protected]
dsh --profile --dump-config # shows the "# == @buberlo/dsh-jev" layer
Do not install @buberlo/[email protected] or @0.1.3. Those tarballs still
contain "@buberlo/jev-core": "workspace:^" (packed with npm, not pnpm).
npm install fails with EUNSUPPORTEDPROTOCOL. 0.1.3 was abandoned: a
granular bypass-2FA token staged the version, and republish returns E409.
0.1.4 is the publish that replaced it. Workspace package.json is 0.1.4.
A checkout packs the same version. Use pnpm so workspace: is rewritten:
pnpm --filter @buberlo/jev-core pack --pack-destination ./packs
pnpm --filter @buberlo/dsh-jev pack --pack-destination ./packs
dsh plugin --profile add ./packs/buberlo-dsh-jev-0.1.4.tgz
# overlay packs/buberlo-jev-core-0.1.4.tgz on the profile
# (see BENCH_LOCAL_PACKS in docs/benchmark.md)
dsh --profile --dump-config # shows the "# == @buberlo/dsh-jev" layer
The bundle inserts one row; configure it by overriding that row's config:
- id: jev
name: '@buberlo/dsh-jev'
config:
provider: mock # mock | live
mode: shadow # off | shadow | enforce
selection: # dynamic tool preselection
enabled: true
alwaysAllow: [read_file]
categories:
files: 'Reading or writing workspace files'
tests: 'Running or inspecting tests'
toolCategories:
read_file: [files]
write_file: [files]
run_tests: [tests]
assessment: # per-call semantic check
enabled: true
onFailure: ask # ask | hold (never an allow)
skills: # route the vendored TypeSafe skill
enabled: true
routingHints:
typesafe-ai: 'especially for TypeSafe/Jev integration, System One models, classifiers'
modelRouting: # map route classes to real models
enabled: false
routes:
fast: { provider: deepseek-official, model: deepseek-v4-flash }
reasoning: { provider: deepseek-official, model: deepseek-v4-pro }
Live API — two explicit settings, never implicit:
provider: live
apiKey: !!js process.env.TYPESAFE_API_KEY
Configure it from the web client
In a web/desktop profile the bundle ships a configuration page: open the
Plugins page and this bundle's own page to find the Jev card. It explains
what Jev does in the loop and edits the safe subset live:
- mode (
off/shadow/enforce) — applied immediately, no restart; - the five feature toggles (selection, assessment, loop guard, skills, model
routing).
Provider, model, and API key stay in cordis.yml (the key is a secret and is
never displayed). Headless profiles have no web client and simply ignore this
half; the plugin runs identically from its composed configuration.
All configuration fields and their defaults
| Field | Default | Meaning |
|---|---|---|
provider |
mock |
answer source |
mode |
shadow |
off / shadow / enforce |
model, apiKey, baseURL |
— | live provider settings (key explicit) |
timeoutMs / budgetMs |
5000 / 8000 | per-attempt timeout / whole-call budget |
maxRetries |
1 | SDK-owned HTTP retries; no second retry loop |
maxConcurrent |
2 | concurrent provider requests |
maxStateChars / maxArgumentChars |
4000 / 1200 | transmitted state and argument bounds |
thresholds.* |
see docs/policy.md |
uncalibrated defaults; tune on your data |
selection.alwaysAllow |
[] |
tools a selection may never hide |
selection.toolCategories |
{} |
tool id → category ids (default: tool id as category) |
loopDetection.maxRepeats |
2 | identical completed calls before the next is held |
skills.routingHints |
{} |
extra routing guidance per skill name |
skills.maxDescriptionChars |
240 | per-part metadata bound |
modelRouting.routes |
{} |
route class → real provider/model |
mock.delayMs / mock.answers |
0 / {} |
deterministic offline scenarios |
logDecisions |
true | structured decision logs |
How the integration stays safe
- No implicit live access.
provider: livewithout an explicit key fails
at plugin load — verified through the realdshloader. - No model-derived permissions. Failures, timeouts, aborts, stale
snapshots, and validation errors produceask/hold; configuration rejects
anything else. - No premature allow. The assessment listener always calls
next()first
and composes monotonically (deny > hold > ask > allow); later policies are
never skipped. - No widening. A Jev selection intersects with existing restrictions and
can only hide tools, never add them. - No stale decisions. Async results are bound to a turn/catalog snapshot;
changed snapshots discard the result and apply the failure rule. - No persistent cache. Approvals are per call; changed arguments are
assessed again. The loop guard is a bounded, deterministic counter. - Bounded, redacted data. Only task text, tool metadata, and bounded
arguments leave the process; redaction is an extra measure, not anonymization.
Measured value
The Kubernetes networking support demo
replays fresh DeepSeek tool calls against a real cluster, with live Jev
assessments, to isolate the gate’s effect from differences in planner choices.
It compares restoration of the portal and preservation of database isolation.
Method, all runs and limits.
Explainer video with narration: English · German
Raw terminal replays: GIF · EN · DE
Jev stopped every attempt: on a weaker model the agent tried to delete the
protected audit trail in 10/10 runs — 31 denials, zero executions — while
without Jev it got through. Footnote, honestly: a rule inside the prompt also
held in our runs and is cheaper. Jev adds an auditable assessment outside the
planning model context; deterministic gates enforce its decisions, but the
model judgments themselves are not a safety guarantee. Full method, raw numbers, videos and limits:
docs/benchmark.md.
Status
| Area | Status |
|---|---|
@buberlo/jev-core |
implemented, 82 unit tests |
@buberlo/dsh-jev |
implemented, 38 integration tests (real ToolRuntime, real agent loop, real approval service, real settings provider) |
| Dynamic tool selection | tested incl. pre-existing denials and parallel sessions |
| Call assessment + approvals | tested incl. changed arguments and fail-closed paths |
| Loop guard | tested (per-agent isolation, shadow vs enforce) |
| Model routing | tested with verified-availability fallback |
| Skill routing + vendored TypeSafe skill | tested against the real filesystem provider |
| Web client configuration page | implemented (bundle-keyed Plugins page); settings write and card interactions tested; module served by a running web app |
Real dsh CLI profile/loader |
verified (see docs/upstream-compatibility.md) |
| Published packages | npm view 2026-09-23: 0.1.0, 0.1.2, 0.1.3, 0.1.4; latest is 0.1.4. @buberlo/[email protected] installs with @buberlo/jev-core@^0.1.4. Plugin @0.1.2 and @0.1.3 are broken (workspace:^) and must not be installed. 0.1.3 abandoned (staged E409). End-to-end dsh profile install was verified for 0.1.0 (2026-09-19), not re-run for 0.1.4. |
| Live TypeSafe API | executed 2026-09-19 (jev-1.13.0): 25/25 fixture agreement, 0 errors, mean 483 ms — a measurement, not an accuracy claim |
| Threshold calibration | pnpm calibrate measures once and sweeps thresholds; live run reports agreement ranges (defaults are inside them), not calibrated operating points |
| Benchmark with/without Jev | executed both tiers plus a use case with video (OpenCode Go, deepseek-v4.1-flash, 10 runs/variant): mock Jev ≈0 overhead; Jev +4.6 s/turn for 3 decisions; baseline destroyed the audit trail in 4/10 runs while Jev denied every attempt — see docs/benchmark.md |
| Code-mode (PTC) | nested dispatch tested; full PTC runtime not mounted |
Repository layout
packages/jev-core/ harness-independent decision core
packages/dsh-jev/ real Cordis/DSH plugin (bundle)
examples/ coding · ops-readonly · standalone-game · DSH runtime
evals/fixtures/ versioned de/en evaluation dataset
.agents/skills/ vendored TypeSafe agent skill (pinned upstream commit)
docs/ architecture · upstream compatibility · policy · evaluation · roadmap · skills · use cases
scripts/ verify.sh · packaging-test.mjs · run-evals.ts
Documentation
| Document | Answers |
|---|---|
docs/getting-started.md |
step-by-step: first run, reading output, going live |
docs/use-cases.md |
what to build and why it works |
docs/architecture.md |
how the pieces fit, extension points, related work |
docs/policy.md |
questions, thresholds, decisions, failure rules |
docs/upstream-compatibility.md |
verified versions, interfaces, limits |
docs/evaluation.md |
mock vs live, dataset, reporting |
docs/skills.md |
the vendored TypeSafe skill and its routing |
docs/roadmap.md |
honest status and limits |
docs/publishing.md |
manual publish runbook (no release automation) |
docs/benchmark.md |
measured with/without-Jev comparison, method and limits |
Development
pnpm install # workspace install
pnpm build # tsc for both packages
pnpm test # 147 tests (85 core + 62 DSH)
pnpm calibrate # threshold sweep over the 25 decision fixtures (mock; --live with a key)
pnpm bench:compare # with/without Jev: real loop, scripted model, no key needed
pnpm bench:cli # CLI A/B run harness (needs an OpenAI-compatible gateway)
pnpm evals # 25 mock evaluation fixtures plus the on-prem support set
pnpm verify # install → build → typecheck → tests → evals → examples → packaging
AGENTS.md holds the permanent project rules (pinned deps, no implicit keys,
monotonic decisions, no release automation).
License
MIT