# @local/dsh-harnessmm [简体中文](README.md) | English A **native plugin for DeepSeek Harness** that implements the **EDG / GDR / CCS** mechanisms from [HarnessMM](https://arxiv.org/abs/2610.32813) (*Recursive Self-Improvement for Harness Token Efficiency*), plus a read-only **session-view** panel (available both as a conversation-view tab and as a right-sidebar tab). GitHub: . - **Host side** (`index.js`): works at the DSH model/tool boundary — injects the Executable Decision Graph (EDG) authoring instruction into the system prompt, wraps the slow model's `llm/stream` output, and performs Guarded Decision Reuse (GDR) against the latest receipt before a tool is dispatched. When eligibility is certified it executes Certified Callback Substitution (CCS) through the native tool interface and appends signed receipts to foreground bash/pwsh results; registers the read-only `harnessmm_status` tool. - **Client side** (`client.js`): registers the two entry points of the 「决策复用」 (Decision Reuse) panel — a conversation-view tab and a right-sidebar tab — reads the host's `harnessmm` session projection, and renders everything **derivable** from the session log: executable decision graphs, guard verdicts, substitution records and measured token usage (read-only; no client→host RPC). - **Zero runtime dependencies**: the host artifact is Node ESM and the client artifact is a browser-side CJS wrapper loaded by DSH's ModuleLoader (React is provided by the host). Neither depends on zod or on `@deepseek-ai/*` packages — the host ships a tiny parse-compatible schema shim instead of zod. The upstream Apache-2.0 `sar_v2.mjs` / `cot_jev.mjs` are vendored verbatim under `src/host/vendor/`. ## Install (one click, from GitHub) Public repository: **** ![Plugin detail page — v0.2.1, component running](docs/plugin-manager-detail.jpg) The DSH plugin page installs directly from a Git URL: the plugin manager installs the package with pnpm and appends packages that declare `dsh.bundle` to `dsh.profile.bundles`; HMR mounts the bundle at profile recomposition — **no app restart required**. 1. Open the DSH Web GUI → **插件 / Plugins** page in the left sidebar; 2. Click **添加插件 / Add plugin** and paste `https://github.com/baipengyan/dsh-harnessmm`; 3. Install, then refresh the page (or wait for the client HMR push). After installation you should see: a **决策复用** tab in the top conversation-view row (right after the built-in Trajectory tab), a **决策复用** tab in the right sidebar, the EDG authoring instruction in the system prompt, `harnessmm_status` in the tool list, and a signed receipt appended to certifiable foreground bash/pwsh results. You can also install the package with the CLI first and then enable the bundle switch in the plugin page (`dsh plugin` only forwards to the package manager; it does not edit the bundles list): ```bash dsh plugin --profile desktop add https://github.com/baipengyan/dsh-harnessmm # Then open DSH Web → Plugins → Installed → HarnessMM 决策复用 and switch it on ``` Requirements: Node ≥ 22.19, DSH `0.2.1-rc.*` (`engines.dsh = ">=0.2.1-rc.2 <0.2.2"`). Build artifacts (`index.js` / `client.js`) are committed, so installing from Git needs no local build. This Git install path has been verified in a temp directory with `pnpm add https://github.com/baipengyan/dsh-harnessmm` (15.3 s, installs 0.2.1 with `index.js` / `client.js` / `cordis.patch.yml` / `locale/` present — see `docs/verification.md`). Uninstall: switch the plugin off on the Plugins page (this removes it from `dsh.profile.bundles`), or delete `@local/dsh-harnessmm` from `dsh.profile.bundles` (the dependency can stay). ## Local development install For source development, mount the package as a link (idempotent; the profile `package.json` is backed up once): ```bash cd harnessmm pnpm install node scripts/build.mjs node scripts/install.mjs # install / repair (link + bundles entry + symlink) node scripts/install.mjs --dry-run # only show what would change node scripts/install.mjs --uninstall ``` `scripts/install.mjs` does three things: 1. registers `"@local/dsh-harnessmm": "link:"` in `~/.dsh/profiles/desktop/package.json`; 2. appends `@local/dsh-harnessmm` to `dsh.profile.bundles`; 3. creates the symlink `node_modules/@local/dsh-harnessmm` in the profile pointing at this directory. DSH's HMR mounts the new bundle at profile recomposition — **no app restart required**; refresh the GUI page to see the result. To disable the engine, add an override entry for `harnessmm` in the profile's `cordis.patch.yml` with `config.enabled` set to `false`, or set `DSH_HARNESSMM_ENABLED=0`. ## Usage ### Conversation-view tab 「决策复用」 A 「决策复用」 tab appears in the top conversation-view row next to the built-in 对话 / 轨迹 tabs (slot `conversation.view`, order 20, right after Trajectory). Clicking it fills the main view: the header is fixed, the body scrolls internally, and the composer never covers the content. ![Decision Reuse panel in the top tab and right sidebar](docs/panel-usage.jpg) ### Right-sidebar 「决策复用」 Open the session right sidebar → 「决策复用」 (`guide` order 42). Both entries render the same panel and read the same projection data. The panel contains: | Section | Content | | --- | --- | | Header | enablement state (host enabled / disabled), current phase (`idle/slow/fast`, heuristic), provider/model/effort route, policy chips | | Token | **measured** input/output/cache tokens and context pressure from the sibling `tokenUsage` / `contextPressure` projections | | Stats | turns / toolCalls / slowCalls / substitutions / certificates / guardsPassed / guardsFailed / banks / nodes / planErrors | | Decision graph | layered EDG: node label, tool, argument preview, guard, successors; node status is currently only `stored` or `substituted`; click a node for arguments, guard, receipt evidence and certificate | | Decision timeline | every tool call as `substitution` (certified replacement) or `slow` (original reasoning callback) with guard verdict pass/fail/unknown | | Plan source | `` JSON (pretty-printed when parseable, raw otherwise) and parse errors | | Certificates | substitution records inferred from the session log (`cert_`); the panel notes that a certificate only means the callback was replaced (CCS happened), not that the call succeeded | | RSI / notes | static RSI snapshot from the host persistence directory (`null` in v1, where RSI is unavailable) and derivation notes | | Empty state | explains EDG/GDR/CCS and how the panel obtains its data | The panel supports local interaction only: collapse sections, filter decisions by `all/substitution/slow`, zoom/select nodes, copy arguments / callId / plan JSON. There are **no** counterfactual "tokens saved / success rate" metrics; a substitution record does not imply success. ### Tool `harnessmm_status` Read-only: reports engine observability counters, the current route, callIds of substitutions awaiting receipts, the policy and the data directory to the agent; it starts no model calls and never reports "saved" or "certified success". In v1, `rsi.available` is always `false`. ## Configuration `cordis.patch.yml` inserts the `harnessmm` row by default and can be overridden by a profile patch: ```yaml - insert: - id: harnessmm name: '@local/dsh-harnessmm' config: enabled: true autoImprove: false # v1: Python RSI training disabled autoImproveAfterTurns: 20 autoImproveCooldownMs: 86400000 iterations: 2 maximumCandidates: 16 # 1..16 (engine value range) maximumFastSteps: 8 # 1..16 (engine value range) maximumPublicBytes: 65536 # 1024..65536 (engine value range; upstream v6 public-state cap is 65536) audit: true # audit sidecar ($DSH_HOME/storages/harnessmm/audit/*.jsonl) ``` `enabled=false` or `DSH_HARNESSMM_ENABLED=0` disables engine behavior entirely (the projection stays registered so the panel still works). The RSI snapshot is read from `$DSH_HOME/storages/harnessmm/stats.json` (or `improvement.json`); when missing it is `null`. The engine hands the vendored graph controller a **trimmed message projection**, not the raw `options.messages`: each user text part is clamped to ≤600 chars, at most the last 32 user turns are kept (new user messages after the plan are always preserved so the controller abstains), and DSH `source`/`id` provenance fields are dropped. Reason: the upstream v6 public-state cap is 65536 bytes (exceeding it falls back to `jev/full-cot` and the slow model). The slow model and the native session log always keep the original messages. ## Honesty boundaries (important) - The view folds **committed session-log events only**; it never reads host memory. The host-side audit sidecar (substitution certificates, admission/fallback reasons, controller-internal events) is **never** written to the session log. - Therefore panel "certificates" are substitution records **inferred** from `chisel__