biuboomc
dsh-plugin-consult
DeepSeek Harness peer-consult plugin: talk to a fork of another session without mutating the original
- Stars
- 2
- Language
- TypeScript
- Created
- Aug 13, 2026
- Updated
- Aug 14, 2026
Introduction
💬 dsh-plugin-consult
Ask the Session that already knows—without rewriting it by default.
|
🧠 Another live Session already investigated the subsystem you are about to touch? |
✨ dsh-plugin-consult turns live Sessions into colleagues.
Ask one peer, reuse the context it already earned, and receive the answer through the current Agent's normal DSH turn. Fork mode protects the source conversation; align mode is an explicit decision to write there.
Question + known facts + assigned tasks → fork by default / align by intent → reply + shared board
Why consult · Features · Install · Quick start · Safety · Technical details
English · 简体中文


Real two-Session acceptance run in DSH Web. The screenshot uses the Chinese DSH locale.
🎯 Why consult
Long-running coding work creates local expertise. One Session may already know the API contract, another the migration, and a third the failing tests. Copying that history into every prompt wastes context and invites drift. dsh-plugin-consult lets the current Agent ask exactly one live peer to use the context it already has.
| Mode | Target | Source Session | Best for |
|---|---|---|---|
Fork, align=false | Reusable working fork A′ | Not written by the consultation | One-way review, fact lookup, and specialist advice |
Fresh fork, fresh=true | New clean fork A″ | Not written by the consultation | A separate answer without earlier consult-channel history |
Align, align=true | Original Agent A | Consultation is written to A's log | Deliberate two-way alignment that both sides must remember |
Fork and align channels may coexist for the same pair of Sessions. The mode is part of the channel identity; switching it is never an invisible side effect.
✨ Features
🧠 Ask the context, not a blank Agent
The system prompt exposes a bounded roster of live peer Sessions by title and ID. When work overlaps, the initiating Agent can call ask_peer instead of searching the same ground again.
Each request can carry:
- the exact
questionto answer; knownfacts the peer should not rediscover;- assigned
taskswith explicit ownership; welcome_questions, allowing the peer to ask the initiator for missing context.
🌿 Protect the source conversation by default
The default channel talks to a working fork A′. Repeated questions reuse that fork and preserve consult continuity without writing the original Session A. fresh=true creates a clean A″ from A's completed history; align=true is the explicit opt-in for talking directly to A.
The acceptance run below asked an API-contract Session for a v2 compatibility review. ask_peer recorded mode: fork, a shared board, and a pending result after the bounded 30-second wait. The reply later arrived through the normal turn.

📋 Carry a shared board, not a vague handoff
Every channel has a board with goal, known, tasks, and questions. Both sides can read or update it with consult_board; only the peer side can use consult_ask to send a clarification back to the initiator. The board is included in consult results so the model and Session log retain the same evidence.
⚡ Wait briefly, then keep working
ask_peer waits only for the caller-supplied wait_ms, and only when the target was already idle and the consult turn started. If the peer is busy, the request is queued without interrupting its current turn. If the reply takes longer than the wait, it is delivered either:
- on the initiator's next tool result through
tools/post-execute; or - as an idle follow-up when the initiator has no more work in flight.
There is no need to busy-poll. consult_progress remains available for a bounded preview, while the full reply is delivered once.
🧹 Inspect, stop, promote, and clean up
Agent tools and slash commands expose channel status, recent progress, cancellation, fork promotion, and cleanup. Working forks are archived from the workspace list and may be disposed after an idle timeout; their logs remain resumable.
⚡ Install
Version 0.1 is a source overlay, not a published standalone bundle. Clone it next to a DeepSeek Harness source checkout, copy the example patch, and replace the placeholder with the absolute path to src/index.ts:
git clone https://github.com/biuboomc/dsh-plugin-consult.git
cd dsh-plugin-consult
cp cordis.yml cordis.local.yml
# Edit cordis.local.yml:
# name: '/absolute/path/to/dsh-plugin-consult/src/index.ts'
cd /path/to/deepseek-harness
pnpm dsh --profile web \
--patch /absolute/path/to/dsh-plugin-consult/cordis.local.yml
Open Settings → Plugins → Plugin list after the Host starts. The consult row should be enabled and mounted. Agent tools become available to eligible live Agents; this is a Host-only plugin and does not add a separate Web dashboard.
The repository currently has no compiled package entry, dependency manifest, release tag, or declared software license. This README intentionally does not advertise an unverified one-line bundle install.
🚀 Quick start
1. Prepare a specialist Session
Let one Session investigate or own a bounded area. It must remain live; cold Sessions need to be resumed before they can be consulted.
2. Ask from another Session
Ask the Session named "API contract owner" to review the v2 error schema.
Known facts: public clients depend on code, message, and requestId.
Have it identify breaking changes and propose the smallest compatible migration.
This is a one-way consultation; do not write the source Session. Wait at most 30 seconds.
The initiating Agent should identify the peer from its roster and call ask_peer with align: false, known, tasks, and wait_ms: 30000.
3. Align only when both Sessions must remember
Align with the evaluation Session on the final acceptance criteria. Write the
decision into that Session too, welcome clarification questions, and wait 30 seconds.
This should use align: true. Align cannot be combined with fresh=true.
🧰 Good consult candidates
| Peer expertise | Focused consult | Why it helps |
|---|---|---|
| API contract owner | Identify breaking schema changes and a migration boundary | Reuses compatibility decisions already present in that Session |
| Security reviewer | Challenge one threat model and list missing controls | Keeps the primary implementation turn focused |
| Test investigator | Explain one failure cluster and the strongest reproduction evidence | Avoids rerunning the same diagnosis in parallel |
| Migration specialist | Review rollback order, invariants, and observability | Brings operational context into the current plan |
| Documentation owner | Check public terminology and compatibility promises | Prevents implementation and docs from drifting |
A strong consult asks one peer one bounded question. If two peers are needed, give them different tasks instead of broadcasting the same problem.
🛡️ Session isolation is not workspace isolation
Fork mode protects the source Session log. It is not a filesystem sandbox.
- A working fork inherits the source Session's cwd and Agent options.
- When the DSH approval service is present, the fork uses approval policy
neverand cannot initiate new peer consults; tools that do not require approval may still be available. - A fork can therefore read or modify the shared workspace if its mounted preset and tools permit it. Use read-only prompts, a read-only preset, or a separate worktree when file isolation matters.
align=truewrites into the original Session and does not restrict that Agent's tools or approvals.consult_stopon an align channel cancels the original Agent's current turn.promote_consultapplies only to fork channels.- Queues and undelivered replies are process memory, not a durable job system.
The plugin prevents accidental conversation mutation by default; it does not replace DSH sandbox, approval, worktree, or policy controls.
🔧 Technical details
🧭 Tools and commands
| Surface | Purpose |
|---|---|
list_peers | List live peers by recent activity, including existing channel identity and mode. |
ask_peer | Open or continue a fork/align channel with a question, board seed, and bounded wait. |
consult_board | Read or update the shared goal, known facts, tasks, and questions. |
consult_ask | Let the peer ask the initiator for clarification; unavailable to ordinary initiators. |
consult_status | Inspect current channel state, queue depth, and delivery state. |
consult_progress | Read a bounded preview of the peer's recent visible output. |
consult_stop | Cancel the current consult turn and return any partial visible text once. |
promote_consult | Promote a working fork into an ordinary independent Session. |
Slash commands: /consult-status, /consult-progress <id>, /consult-stop <id>, /consult-promote <id>, and /consult-cleanup.
⏳ Asynchronous states
ask_peer result | Meaning |
|---|---|
ready | The idle target finished within wait_ms; the reply is returned immediately. |
pending | The consult turn started but did not finish within the bounded wait; delivery remains queued. |
queued | The peer was already busy; the question waits without interrupting its current turn. |
stopped | The consult was cancelled while waiting. |
Only the first consult wait in one Agent step may block. A busy target or a later consult in the same step returns immediately. Results include the channel mode, fork disposition (new, continued, fresh, or source), and the current board.
🏗️ Cordis architecture
flowchart LR
Roster["System-prompt peer roster"] --> B["Initiator Agent B"]
B --> Entry["Agent tools / slash commands"]
Entry --> Service["Consult service"]
Service --> Channels["Channel index + queue"]
Channels --> Fork["Working fork A′ (default)"]
Channels --> Align["Original Agent A (explicit align)"]
Logs["Session log markers: result + board"] <--> Service
Fork --> Delivery["Reply delivery"]
Align --> Delivery
Delivery --> Hooks["tools/post-execute or idle follow-up"]
Hooks --> B
Lifecycle["Cordis lifecycle + workspace registry"] --> Fork
The channel index is a runtime projection. On entry, the plugin scans live Session logs for [consult-result] and [consult-board] markers, reconnects known working Session IDs, and resumes an archived fork when needed. Disposal archives and releases plugin-owned working forks; it never archives or disposes the original align target.
⚙️ Configuration
| Option | Default | Meaning |
|---|---|---|
maxRounds | 8 | Maximum consult rounds per channel, including queued work. |
maxWaitMs | 180000 | Upper bound for one synchronous wait request. |
maxAskBack | 4 | Maximum clarification questions from the peer. |
archiveWorkingForks | true | Hide plugin-owned working forks from the normal workspace list. |
forkIdleMs | 1800000 | Dispose an idle working fork after 30 minutes; 0 keeps it live. |
🚧 Current limits
- Only live Agents appear in the peer roster; cold Sessions must be resumed.
- Fork mode requires a completed source turn. Align can target a live Agent without one.
- If the initiator ends and never runs another tool, an undelivered reply remains queued until its next activity.
- Queue and delivery state do not survive a Host restart, although log markers can rebuild the channel index.
- This plugin has no custom Web UI, worktree isolation, cross-Host coordination, or durable background-job queue.
- A promoted fork is an ordinary Session and is not automatically archived.
🧪 Development and verification
This README update was verified with a real two-Session acceptance run in DSH Web:
- Session A recorded an API compatibility contract.
- Session B opened a default fork consultation with a 30-second wait.
ask_peerreturnedpending; the shared board completed asynchronously.- The reply arrived in B, which produced the three-point review shown above.
- Opening A again showed only its original turn, confirming that fork mode did not write the source log.
The compatibility patch in this branch also makes every nested board object schema explicit for the current Harness validator.
The repository does not currently declare a software license. Public visibility alone does not grant reuse or redistribution rights; maintainers should choose and add a license before publishing a distributable package.