outnever
dsh-research-first
Research-first assistant for DeepSeek Harness: gently nudge agents to investigate docs/code/community before editing
- Stars
- 1
- Language
- JavaScript
- Created
- Aug 14, 2026
- Updated
- Aug 14, 2026
Introduction
dsh-research-first
A research-first assistant plugin for DeepSeek Harness (DSH).
Gently nudges the agent to do a cheap, deterministic investigation before editing code — without hard-blocking (so "can't reach docs" never stalls the work).
agent about to write/edit/bash without investigating
│
▼
soft nudge: allow + inject a reminder (model-visible, logged)
│
investigation blocked (web_search failed / GitHub unreachable)
│
▼
remind the user why, offer to continue anyway — fully logged, replayable
Why
Three real failure modes of LLM coding, which compound each other:
| Failure | Symptom |
|---|---|
| Guessing before acting | Writes code from memory instead of checking requirements / API / docs |
| Trial-and-error loops | Repeated failures without looking up known community workarounds |
| Stale knowledge | Acts on outdated versions / endpoints that have since changed |
The core insight: one cheap lookup prevents one expensive rework.
Design philosophy
Make "verify first" a preferred attempt + frictionless nudge + blocked-notice + full trace, not a hard prerequisite.
Why not hard-block? Investigation can be genuinely impossible (air-gapped environments, network restrictions, no official docs). If "can't verify" halts development, the cure is worse than the disease. So the default is a soft nudge — remind without blocking, leaving the choice to the agent and the user.
| Behavior | Description |
|---|---|
Soft nudge (default remind) | Editing without investigating → not blocked, but a reminder is injected (model-visible + logged) |
| Blocked-research detection | Investigation tools (web_search, etc.) failing → reminder: "research blocked, ask the user whether to continue" |
| Research-norm injection | Adds "golden research habits" to systemPrompt: search with versions, prefer official tools, explain when blocked |
| Failure reminder | After repeated failures, remind to check community feedback (GitHub issues) first |
| Full trace | Every reminder is a plugin-sourced message in the session log — replayable, auditable |
Set intensity: warn (hold for approval) or intensity: block (deny) when you want hard enforcement.
Comparison with similar plugins
| Plugin | Focus | Difference from this one |
|---|---|---|
dsh-doublecheck | Engineering-discipline gates (grill requirements, red/green tests, adversarial review) | Defaults to hard enforcement; this plugin defaults to soft |
dsh-pain-point-check | Veto-based stop after failed experiments | It denies non-investigative tools; this plugin reminds without blocking |
| dsh-research-first | Lightweight research-first assistant | Frictionless, non-blocking, hands decisions back to the user when blocked |
They compose — use doublecheck for strict discipline, or this plugin for a lightweight, unobtrusive default.
Install
Option 1: official (recommended, needs pnpm)
dsh plugin --profile web add github:outnever/dsh-research-first
Restart:
dsh web
Option 2: manual (no pnpm)
# 1. symlink into the profile's node_modules
ln -sfn /absolute/path/to/dsh-research-first ~/.dsh/profiles/web/node_modules/dsh-research-first
# 2. add to ~/.dsh/profiles/web/cordis.patch.yml:
# - insert:
# - id: research-first
# name: 'dsh-research-first'
# config: { intensity: remind }
# 3. restart dsh web
Verify:
dsh --profile web --dump-config | grep -A2 research-first
# expect: id: research-first / name: dsh-research-first / intensity: remind
Configuration
| Field | Default | Meaning |
|---|---|---|
intensity | remind | remind (nudge) / warn (approval) / block (deny) |
failureThreshold | 2 | Consecutive failures before the community-check reminder |
injectNorm | true | Whether to inject the research norm into systemPrompt |
detectBlocked | true | Whether to detect failing investigation tools and remind |
investigationTools | read, grep, glob, web_search, read_image, ask_user_question, skill | Tool names counted as "investigation" |
mutationTools | write, edit, bash, pwsh, str_replace_editor | Tool names counted as "editing" |
How it works
Built on DSH's official extension points only — no private machinery:
tools/pre-execute(waterfall): mark investigation / decide allow · remind · denytools/post-execute(waterfall): injectadditionalContextsreminders, detect blocked research, count failuresagent/pre-step(waterfall): reset the investigation flag onstep===1systemPrompt.section: inject the research norm
Key implementation detail: reminders are hand-written UserMessage shapes ({ id, role:'user', content, source:{kind:'plugin',...} }) with id from Node's built-in crypto.randomUUID(), keeping zero dsh package imports — so the plugin loads via symlink without pnpm resolving dependencies.
Testing
node test.mjs
# 19 mock unit tests: soft nudge, blocked-research, failure reminder, block/warn modes, norm injection, turn reset
Runs with no dependencies — lib/index.js only imports node:crypto.
Known limitations
- The
remindreminder is a soft hint in the session — not enforced; the model may ignore it. Useblockto enforce. - "Search with versions / prefer official tools" is soft-guided via systemPrompt — rules can't hard-guarantee it (it's ultimately the model's willingness).
Contributing
Issues and PRs welcome. When changing:
- Keep zero dsh package imports (prerequisite for symlink loading without pnpm);
- Update
test.mjsand keepnode test.mjsgreen; - Update the README's behavior description.