dsh — DeepSeek Harness adapter

Spike of the claude-harness port for DeepSeek Harness (DSH 0.2.1-rc.3). The Claude Code installation in ~/.claude stays untouched; this directory is a separate Cordis bundle plus a thin install helper.

What works in the spike:

  • guard-main / require-plan — the tested bash/Python hooks run through ctx.tools.guard; the agent gets BLOCKED with the same messages as in Claude Code;
  • superpowers bootstrap — using-superpowers is injected once per session from agent/pre-step and re-injected after compaction;
  • /role dev|admin|analyst|qa — reads both role layers and injects the role text, without Claude's auto-memory step.

Not yet: SDD (DSH subagents are asynchronous), briefing, harness-check, role-hint, harness-doctor, auto-memory, caveman. See PORT.md for the design, mapping table, and risks.

Quick start

# Static check
bash dsh/install.sh --check

# Global instructions and superpowers skills
# (run from a terminal; these write outside the session workspace)
bash dsh/install.sh --global
bash dsh/install.sh --skills

# Install the bundle in DSH:
#   Plugins -> install a bundle from dsh/bundle
#   or ask the agent to call plugin_manager install_bundle with that target.

Do not hand-edit $DSH_HOME/profiles/desktop/package.json or cordis.patch.yml: the Desktop profile is Electron-managed and the plugin manager owns those writes.

Verify

  1. In a new session, ask what skills do you have? — the superpowers catalog should be visible.
  2. In a repository on main, ask the agent to create a file — expect BLOCKED [guard-main].
  3. Create a worktree on a feature branch, ask for an edit under src/ — expect BLOCKED [require-plan] until .bounded or a plan for the branch exists.
  4. /role dev — expect the five-line role summary.
  5. Prompt Let's make a react todo list — brainstorming must trigger before any code.

The injected bootstrap starts with a marker:

<!-- DSH-HARNESS-BOOTSTRAP:<16-hex-hash> -->

After compaction the marker disappears from session.surface.nodes and the next step injects a fresh copy.

Tests

bash dsh/tests/run.sh

Pure Node; no DSH process is required. The guard tests create a throwaway git repository and exercise the real hooks/guard-main.sh and hooks/require-plan.sh through the adapter.

Layout

dsh/
  bundle/
    package.json          DSH bundle manifest (dsh.bundle.patch)
    cordis.patch.yml      inserts the dsh-harness row
    index.js              ctx.tools.guard + agent/pre-step + /role
    command-role.js       /role command glue
    lib/guards.js         DSH tool call -> claude-harness hook JSON
    lib/bootstrap.js      superpowers skill resolution, marker, dedupe
    lib/role.js           role layers and text (pure)
    dsh-tools.md          superpowers tool mapping
    hooks -> ../../hooks  local install: tested hooks are reused, not copied
    locale/{en,ru}.json
    icon.svg
  tests/
  install.sh
  mcp.codegraph.yml       optional CodeGraph MCP overlay
  PORT.md                 design, mapping, risks, next phases

Configuration

The row is configurable from the profile patch; defaults target this repository layout:

- id: dsh-harness
  config:
    guards: true
    bootstrap: true
    roleCommand: true
    bootstrapSubagents: false
    hooksDir: ''             # empty -> bundle/hooks -> ../../hooks
    rolesDir: ''             # empty -> installed ~/.claude/roles, else repo roles/
    projectRolesDir: ''      # empty -> <cwd>/.claude/roles
    roleNames: [dev, admin, analyst, qa]
    bootstrapSkillPath: ''   # empty -> newest superpowers plugin cache
    toolMappingPath: ''      # empty -> bundle/dsh-tools.md
    bootstrapMaxBytes: 65536

Known limits

  • The guard adapter uses the repository's bash/Python hooks; if python3 is missing, the hooks fail open by design.
  • bundle/hooks is a symlink for local-directory installation. A published bundle needs a real copy of hooks/ (already listed in package.json files).
  • using-superpowers content is read from the installed Claude plugin cache; set bootstrapSkillPath or DSH_SUPERPOWERS_SKILL for another layout.
  • Model names in roles and superpowers (sonnet, haiku, opus) are not DSH models. Map them to live provider/model routes before porting SDD.
  • SDD is intentionally out of scope for this spike; see PORT.md.