← Back to home@yxdotnet

dsh-persona-driven

dsh-persona-driven,dsh技能插件,人格驱动引擎

Stars
0
Language
Python
Created
Oct 16, 2026
Updated
Oct 17, 2026

Introduction

persona-driven · Persona-Driven Engine (DeepSeek Harness plugin)

Turns "the AI is too cautious, re-tests every tiny change, burns tokens" into eight adjustable dials. One sentence — "be decisive" — switches the profile. This repository is the native DeepSeek Harness port of the persona-driven skill: a bundled skill, per-turn injection and a hard safety floor, all on native Cordis extension points. No Git Bash, and no per-turn Python subprocess.

中文 · Changelog · Install & verify · Architecture & porting notes · Release & distribution

topic: dsh-plugin license: MIT


In 30 seconds

You do not need to know MBTI. MBTI is just a memorable handle; the dial values are what actually take effect.

You wantJust say
Go faster, stop over-testing"be decisive", "stop re-testing everything", "too many tokens"
Name a type"use ENTJ", "switch to ESFP"
Use a preset"Fast mode", "use the steady one", "give me a few options"
Inspect / turn off"what persona am I on", "turn off persona"
See your data"persona dashboard"

Eight dials, each 1–5:

GroupDialAnswers
ExecutionPACEhow often to stop and ask
ExecutionVERIFYhow much verification this change gets
ExecutionRISKhow much uncertainty is acceptable
ExecutionSTRUCTwhether existing structure may move
CognitionDETAILhow much detail to give
CognitionEXPLOREhow many options to offer
InteractionSTYLEhow to talk
InteractionWARMTHattend to the person or the task first

Four presets — Fast (P5/V4/R4/S4/D5/E1/ST3/W2), Steady, Explore, Companion — plus all 16 types. Eight domains (coding, UI design, visual image, finance, writing, planning, collaboration, decision) each have a dial→output mapping; only the relevant one loads.


Two floors that never come down

Safety floor. Deleting/overwriting, payments, auth and permissions, secrets and credentials, production changes, destructive database statements, irreversible actions — the profile always reverts to high verification and asks first. Once this plugin is installed, that becomes a real approval prompt via tools/pre-execute (not just the model's good intentions).

Verification floor. The profile tunes how much extra verification happens, never whether anything is verified. Whatever you change gets verified; introducing new behaviour or fixing a defect requires fixed, re-runnable evidence, self-reported on the last line. It is decoupled from EXPLORE and PACE — "only one option" and "just be quick" are never reasons to verify less.

Savings may only come from getting it right the first time, never from doing less. A rework is treated as a signal that earlier verification was under-funded: catch up, do not keep skipping.


Install

Install — one command (installing the plugin is L3)

dsh plugin --profile <profile> add github:yxdotnet/dsh-persona-driven

That single command installs the package and writes @dsh-external/persona-driven into the profile's dsh.profile.bundles; restart DSH and it is live. The same spec can be pasted into the Plugins page in DSH's Web sidebar.

Measured: pnpm finishes in 9.1 s; dsh <profile> --dump-config shows - id: persona-driven with zero warnings. Once published to npm, the equivalent is add @dsh-external/persona-driven.

No hooks to install. On DSH the three capabilities — per-turn injection, safety-floor interception and telemetry — are carried by the plugin itself (native Cordis extension points). Once the plugin is installed there is no hooks config file and no per-turn subprocess; ~/.dsh/persona/ only ever contains metrics/ and sessions/.

It is the plugin, not the skill directory, that provides L3 — copying the skill directory alone gives you no injection and no guard. The hook bridge below exists only to keep older configs working — not recommended, ignore it for a fresh install.

Degraded — without the plugin (L1/L2, not an install option)

Copy skills/persona-driven/ into a DSH skill root; DSH discovers it automatically.

# Windows PowerShell ($env:DSH_HOME defaults to ~/.dsh)
Copy-Item -Recurse -Force .\skills\persona-driven "$env:USERPROFILE\.dsh\skills\persona-driven"
# macOS / Linux
mkdir -p ~/.dsh/skills && cp -r skills/persona-driven ~/.dsh/skills/

DSH skill roots, lowest rank wins:

RankPathScope
100<projectRoot>/.dsh/skillsproject
200<projectRoot>/.agents/skillsproject
300customSkillDirs from the compositionconfigured
400$DSH_HOME/skillsuser
500~/.agents/skillsuser
600bundled skill dir / $DSH_BUNDLED_SKILL_DIRinstallation

<projectRoot> is the nearest ancestor containing .git.

This level can influence, not constrain: tone, detail and pace follow the profile, but test depth is not enforced and the safety floor does not force a human confirmation.

Install from a local directory (dev mode) — also L3

The plugin registers the skill, injects the dial block every turn, and turns the safety floor into a real approval prompt.

# add it to a profile (<profile> is desktop / web / tui / ...;
# replace <path-to-this-repo> with where you cloned it)
dsh plugin --profile <profile> add <path-to-this-repo>

# then restart DSH — no hand-editing of the bundle list; the command above does it

The command rewrites dsh.profile.bundles to include:

{
  "dsh": {
    "profile": {
      "bundles": [
        "@deepseek-ai/dsh-base",
        "@deepseek-ai/dsh-web-app",
        "@dsh-external/persona-driven"
      ]
    }
  }
}

You can also install it from DSH's plugin panel (plugin_manager → install_bundle, with this directory's absolute path as target).

Plugins are modules DSH loads at startup; restart DSH for changes to take effect.

Hook bridge (not recommended; kept for older configs only)

A compatibility path: generate a Claude Code-format hooks.json and let DSH's bundled @deepseek-ai/dsh-hooks-claude-code bridge run it.

cd skills/persona-driven
python scripts/persona.py install-hooks                        # preview, writes nothing
python scripts/persona.py install-hooks --apply --write-confirmed

Then add the YAML the script prints into $DSH_HOME/cordis.patch.yml (or the profile's own) and restart DSH:

- insert:
    - id: persona-driven-hooks
      name: '@deepseek-ai/dsh-hooks-claude-code'
      config:
        configPath: <the hooks.json path printed above>

Pick one of A / B / C. Options B and C both inject every turn; enabling both injects the dial block twice (same content, pure token waste).


Verify it actually works

cd <path-to-this-repo>
npm test        # 273 assertions + install self-check (84 need a DSH node_modules; that suite reports "skipped, unverified" without one)
npm run doctor  # install self-check only

npm run doctor reports four things: package and patch integrity, skill payload completeness, whether the bundle is installed into any profile, and whether the state directory is writable. The criterion is "installed", not "the command exited 0".

Skill-side checks:

cd skills/persona-driven
python scripts/persona.py doctor   # environment + DSH plugin + optional hook bridge
python scripts/persona.py get      # the effective profile and which layer it came from

What this plugin does

ItemBehaviour
Injection channelagent/pre-step waterfall — native, no subprocess
Dependenciesnone (Python is only needed for the CLI: switching dials, dashboard)
Safety floortools/pre-execute returns {kind:'ask'} → DSH Approval service
State root$DSH_HOME/persona (default ~/.dsh/persona)
Project layer<cwd>/.dsh/persona — resolved to the git root, same as the plugin
Session idDSH_SESSION_ID (older names still fall back)
Web panelread-only status pill; off by default (see below, it cannot read the data)
Re-inject after compactionunsupported (see below)

The web pill is off by default (it cannot read the data)

lib/client.js is not enabled by default. Not to save effort — it cannot obtain what it is supposed to show:

  • the host renders conversation.composer.dock with empty props (literally renderSlot("conversation.composer.dock", {}) in the host source);
  • the session id is not in the page URL, and the client exposes no injectable session service (only slots and the like).

So the pill can only fetch without ?session=, and the route falls back to the global layer when no session id is given — but since v1.5.33 dials are written to the session layer by default, the global layer is usually empty, so persona is null, the component returns null, and the pill never appears. Measured:

RequestResponse
no ?session= (what the client does){"layer":"global","persona":null}
?session=<this session>{"layer":"session","persona":"ENTJ","dialsText":"P5/V3/R4/S2/D4/E2/ST4/W1"}

Turning on webPanel: true only makes sense when a global persona is set explicitly (set … --scope global) — then the route reads the global layer and the pill is correct. Better off by default than shipping something that looks like it works and does not.

One real, minor regression: PreCompact

The upstream version registered five hook events. DSH's Claude Code bridge supports four: SessionStart, UserPromptSubmit, PreToolUse, PostToolUse. PreCompact is not supported on DSH, so it has been removed from the hook generator.

  • With the hook bridge: after a context compaction the dial block is not re-injected.
  • With the native plugin: unaffected — agent/pre-step runs every turn.

Layout

package.json              DSH bundle manifest (dsh.bundle.patch + dsh.client)
cordis.patch.yml          bundle layer: inserts the persona-driven row
icon.svg                  plugin icon
locale/{zh,en}.json       plugin panel title and description
lib/index.js              Host half: skill provider, per-turn injection, guard, metrics, route
lib/persona-core.js       platform-neutral core (Node builtins only; testable without DSH)
lib/client.js             Client half: read-only status pill, shared by web and desktop
lib/skill-meta.json       single source of truth for skill name / description / whenToUse
skills/persona-driven/    the full skill payload
tests/                    re-runnable verification
docs/                     install & verification, architecture & porting notes

Requirements

  • Full access (DSH's Full access mode) — required. The skill runs shell commands (python scripts/persona.py …) and writes outside the session workspace to $DSH_HOME/persona/ (dials, metrics, session profiles). Without it, set / off / the dashboard / doctor fail on a denied write. The plugin removes the shell from per-turn injection and the safety floor, but these CLI operations still need it.
  • DSH (needed for the plugin form; not needed when only copying the skill directory).
  • Node ≥ 20 (the plugin half; Node builtins only, zero npm dependencies).
  • Python ≥ 3.10 (only for scripts/persona.py; standard library only).
  • Git Bash — no longer required.

Privacy

Metrics record tool names, classification flags, timestamps, the persona name and a hashed prefix of the session id. They do not record command text or prompts by default, and nothing leaves the machine. Data lives in $DSH_HOME/persona/. PERSONA_LOG_COMMANDS=1 is the single opt-in exception, off by default.


Honest disclosure: the effect is unproven

The core hypothesis ("the profile reduces verification investment") has been tested in three controlled rounds and fails its pre-registered decision line. The latest round, v3 (300 runs = 10 tasks × 10 repetitions × 3 arms, single model):

  • median tool calls 12 → 7.5 (down 37.5%, 95% CI 27%–50%), direction holds and the dose-response is monotonic;
  • but missed verification degrades significantly (C 79/100 vs control 48/100, p<0.0001), and the effect depends heavily on task type (21%–56%).

Therefore:

  • do not trust any token-reduction number;
  • do not claim that missed verification is solved or that the mechanism works;
  • per-item data may be disclosed, but always with the overall verdict: not established.

The authoritative wording lives in skills/persona-driven/references/limits.md — all public claims must follow that file. Two further limits must be stated alongside it: triggering is probabilistic (measured: the same sentence twice, one hit one miss; naming a type explicitly is far more reliable), and of the three floors only the safety floor has runtime enforcement — the verification floor and "first time right" are written rules plus per-turn injection, and depend on the model following them.


License

MIT — see LICENSE. Skill content © 多汁牛排 (original author); DSH plugin port and packaging by yxdotnet.