dsh-swarm
Curated pickMaintenance: Activejoekytc/dsh-swarm
Run multi-agent task pipelines on DSH like a team — plan, execute, review, and deliver code through a visual kanban with provable completion.
$ dsh plugin add dsh-swarmInstall
dsh has no central install command — add this plugin’s entry (documented in its README below) to your profile or patch config, then restart.
How installs work5
stars
0
forks
TypeScript
Language
MIT
License
2026-08-20
Created
2026-09-21
Last push
README
dsh-swarm
Say one requirement, reply one confirmation — six specialist agents take it from planning to verified delivery. No commands to memorize.
dsh-swarm is a DSH plugin that turns one requirement into a strict, evidence-verified delivery pipeline. An orchestrator (V) decomposes an approved spec into a strictly ordered phase chain (p → (pt?) → w2 → d → dt → w3 → summary); six single-purpose roles (V / P / W / D / PT / DT) run each phase with isolated, permission-gated tool faces; every handoff is machine-verified against an evidence contract; failures recover through idempotent retry and human-gated reviews; and a live Workflow kanban tab streams all state to the browser via SSE. Design inspired by the Hermes Agent kanban.
Swarm mode (recommended)
Swarm mode turns your main session into a team lead: you state the requirement, it clarifies, plans, confirms, delegates and follows through — entirely in natural language, no commands to remember.
- No commands to memorize — just state your requirement; no
/plan:or/openspec:prefixes needed. - Automatic intent recognition — development requests → clarify/plan and build a chain; lessons & retrospectives → persist to memory; group notifications → deliver to WeCom; Q&A / chit-chat → answered directly. Intent is judged by the model, not by a code-level classifier — the confirmation gate below is what stops a misjudged chain.
- Free delivery —
/sms <intent>(e.g. "post current progress to the group"): facts are grounded via kanban lookup, then the body is composed per intent and delivered;-sor wording like "private chat" targets the DM. A bare/smsre-sends the latest completed-chain report and/sms blocked [chainId]the block notice — those two bodies are rendered by system code from kanban facts, never rewritten by the lead. Group and private-chat targets auto-resolve to the single saved target (0 or 2+ targets error out; clean up in dsh-im settings, or pinimDelivery.targetId/imDelivery.dmTargetId, which skips the count check — though withimDelivery.botIdempty the pinned target must still belong to the auto-discovered bot, or it errors out). - Confirmation gate against accidental chains — after the checklist is saved, the lead is instructed to build a chain only once you reply with an explicit affirmative (
确认/开干/开跑/开始/go, etc.). The gate is judged by the model, not enforced by a code-level check; vague replies, topic switches, or edit-only feedback count as not confirmed. - The lead is read-only — the main session cannot write/edit repo sources, nor run git mutations (push/commit/reset…); a bare
git checkout/git switchof an existing branch is allowed. Writing code is done by the executor (D) in an isolated workspace by design. - Progress is always actually queried — ask "how is it going?" anytime and the lead reports from real kanban lookups, never fabricated.
Why it's designed this way
Coordinating several agents on one task typically fails in three ways:
- Role drift — the "planner" starts writing code, the "executor" reviews its own work, and nobody owns the outcome.
- Unverifiable handoffs — an agent claims "done" with no reproducible evidence, and the next agent builds on sand.
- Silent deadlocks — an agent stops without finishing and the pipeline hangs, or bad code is merged before anyone reviewed it.
dsh-swarm encodes a contract against all three: one responsibility per role, enforced by the permission matrix, tool faces and task-body instructions; every handoff must carry structured evidence or the phase will not close; every stall or review failure lands in a visible, recoverable state — with you (the human) as the final trust anchor. It is built correctness-first: deterministic state machines, append-only event sourcing, idempotent schedulers, and a red-team test suite that replays the event log and rejects any illegal transition (mechanics in Advanced).
Two modes
| Mode | How you use it | Notes |
|---|---|---|
| Swarm mode (recommended) | Just say the requirement in natural language | No commands to memorize, intent auto-recognized, runs on confirmation |
| Command mode (compatible) | /plan: <requirement> → clarify → /openspec: confirm |
Kept for compatibility, functionally equivalent; may be removed in the future — new users should use swarm mode |
Quickstart
1. Install
Prerequisites: a working DSH runtime (@deepseek-ai/*), Node.js ≥ 22.19 and npm. Optional: a wiki-vault HTTP service (KB features, see Configuration).
From npm (the published tarball ships the built lib/):
dsh plugin --profile web add @joekytc/dsh-swarm
From a source checkout (rebuild first so lib/ matches the sources):
npm install
npm run build # tsc -p tsconfig.build.json + client bundle (lib/client.js)
dsh plugin --profile web add .
From GitHub source:
dsh plugin --profile web add github:joekytc/dsh-swarm— the repository tracks the builtlib/.
2. Switch your main-session preset
Switch the main session's agent preset to Swarm (蜂群模式) — it is installed at $DSH_HOME/.agent-presets/swarm once the plugin is installed.
3. Say → confirm → watch progress
Example conversation:
You: Add a role-management page to the admin project with CRUD and permission checkboxes
Lead: Let me confirm a few things first —
· Which role fields do you need (name/description/status/…)?
· Permission source: the existing menu tree, or custom?
· Any acceptance requirements, e.g. "deleting a role must not affect linked users"?
You: Fields are name and description, permissions from the existing menu tree, acceptance via TDD
Lead: Checklist saved (six spec sections + repo facts). Reply "confirm" to launch —
I'll spin up the p → (pt) → w2 → d → dt → w3 pipeline.
You: confirm
Lead: Chain created (ch_…), live progress on the kanban tab (Conversation → Trajectory → Kanban).
First phase: Planning (P)…
- Kanban: the third tab of the conversation center (Conversation → Trajectory → Kanban). Click a card for Overview / Trajectory / Handoff / Spec / Comments.
- Completion: when a chain completes, the system audits the workspace and (for D chains) automatically merges the feature branch into the spec-declared target branch. An audit warning blocks the final wrap-up until you confirm ownership in the GUI — it does not gate the merge.
- Progress: just ask "how is it going?" — the lead reports from real kanban lookups and relays blocking reasons faithfully.
What it does for you
Six roles, one job each — boundaries enforced by the permission matrix, trimmed tool faces and task-body instructions, so no role creep:
| Role | One-line responsibility | What it never does |
|---|---|---|
| V Orchestrator | Creates phase cards, drives the pipeline, gives guidance on stalls | Never executes |
| P Planner | Reads the spec + repo facts, writes the implementation plan | Never writes code |
| PT Plan reviewer | Read-only review of P's plan (on demand) | Never changes anything |
| W Knowledge officer | Syncs the KB in planning/completion phases | Never touches code/git |
| D Executor | The only role that writes code: implement → verify → commit → push feature branch | Never merges into the target branch itself |
| DT Implementation reviewer | Empirically verifies D's delivery (tests/build/typecheck/diff) | Read-only against the repo |
The pipeline (strictly serial within a chain, parallel across chains):
p ──> (pt?) ──> w2 ──> d ──> dt ──> w3 ──> summary
plan plan rev. KB impl impl rev. KB wrap-up
ptappears only when P decides a plan review is needed;dis always followed by an implementation review (dt).- Chain completion is decided by a mechanical rule (W3 done + D done with delivery evidence + no open tasks), not by an agent's self-assessment.
Configuration
All keys are optional; schema lives in src/config.ts. Most users only need the first three — keep the rest at their defaults.
| Key | Default | Description |
|---|---|---|
storageDir |
$DSH_HOME/storages/kanban |
Event log (events.jsonl), orchestration state, per-task workspaces, dispatcher.log. Value must use the unquoted !!js dshHomePath("storages/kanban") form — quoting degrades it into a literal string |
wikiVault.baseUrl |
'' (empty) |
wiki-vault HTTP service for KB reads/writes — required for KB features; set to your own server |
wikiVault.pagePrefix |
projects/ |
Namespace prefix for generated wiki pages |
roles.models.<role> |
{} |
Per-role model: { provider, model, reasoningEffort?, fallbacks?[] } |
roles.models.<role>.reasoningEffort |
high |
Default reasoning effort for all roles |
roles.models.<role>.fallbacks |
[] |
Silent fallback candidates (audited via [model-fallback] comment) |
dispatcher.staleTimeoutSeconds |
14400 |
Heartbeat timeout; running task without heartbeat is reclaimed |
dispatcher.maxRetries |
3 |
Failure retries before circuit → blocked(gave_up) |
dispatcher.heartbeatIntervalSeconds |
300 |
Watchdog heartbeat period |
dispatcher.maxProtocolViolations |
2 |
Protocol-violation guardrail: once consecutive violations reach this many, the next one is final (gave_up) |
dispatcher.maxReworksPerRole |
{ pt: 3, dt: 3 } |
Max review rework rounds before review/gave-up + [review-final] |
prefixRoutes.plan |
/plan: |
Command-mode phase-0 planning prefix |
prefixRoutes.openspec |
/openspec: |
Command-mode approve-and-execute prefix |
prefixRoutes.learning |
/learning |
Lessons / retrospective prefix |
prefixRoutes.send |
/sms |
Free-delivery prefix (DM with -s) |
memory.enabled |
true |
Memory recall index; false makes planning_memory_recall return a disabled notice |
memory.maxIndexEntries |
8 |
Max recalled memory entries (1–20) |
ui.enabled |
true |
Declared switch; not consumed yet — the tab registers unconditionally |
ui.contentMinWidth |
715 |
Declared lower width bound (px); not consumed by the client yet — the tab follows the host conversation width |
ui.contentMaxWidth |
780 |
Declared upper width bound (px); not consumed by the client yet |
ui.sseHeartbeatSeconds |
20 |
SSE heartbeat interval |
gates.enabled |
true |
TDD measurement gate; false → silent skip (no event) |
gates.timeoutMs |
600000 |
Per-command gate timeout (ms), SIGKILL at the deadline |
gates.forbidden |
['rm -rf /', 'git push'] |
Command-blacklist substrings (defence in depth) |
evidenceReplay.enabled |
false |
L3 replay of model-written commands — not a sandbox, see Issue evidence check |
evidenceReplay.timeoutMs |
600000 |
Per-replay command timeout (ms) |
evidenceReplay.allowPrefixes |
['npx --no-install vitest', 'npm test', 'npm run build', 'npm run typecheck', 'tsc', 'eslint'] |
Allowlisted tool prefixes (word-boundary match) |
imDelivery.enabled |
false |
WeCom delivery via dsh-im (W3 wrap-up / chain blocked / review gave-up) |
imDelivery.botId |
'' |
Empty = auto-discover the only wecom bot |
imDelivery.targetId |
'' |
Empty = auto-discover the only saved group target |
imDelivery.dmTargetId |
'' |
DM target for /sms -s |
imDelivery.fallbackBotId |
'' |
Bot used when preset-based matching finds nothing |
reviewEngine.mode |
delegate |
delegate or managed — see Review engine (ocr) |
reviewEngine.managed.provider |
'' |
Model-chain provider id used in managed mode |
reviewEngine.managed.model |
'' |
Model-chain model id used in managed mode |
wikiWritePresets |
['swarm', 'kanban-w', 'ptc'] |
Presets allowed to call wiki_write (page paths are still whitelisted by namespace) |
Review engine (ocr)
Implementation reviews (the in-chain DT phase and standalone reviews) are powered by open-code-review (ocr), with two modes switchable in the web config panel under 「Swarm 配置 → 评审引擎(ocr)」 (Swarm config → Review engine (ocr)):
| Mode | How it works | Notes |
|---|---|---|
| Delegate (default) | ocr only outputs the review scope and rules; DT reviews each file with its own model | Zero API keys, works out of the box |
| Managed | ocr runs the full review with your chosen provider/model and returns normalized findings in one shot | For large change sets; delegate mode hints at switching past 50 files (a hint only, never auto-switched) |
Install
- When ocr is missing, the config panel shows a red banner — click 「安装 ocr」 (Install ocr) for a one-click global install (async, cancellable);
- or run
npm install -g @alibaba-group/open-code-reviewin a terminal, then verify withocr --version.
Standalone review (no chain needed)
- Switch the session to 「交付评审官(DT)」 (Delivery Reviewer (DT)) at the top of the dsh web UI and just talk;
- State the review target: a local directory / branch range (from…to) / a single commit / uncommitted workspace diff / a public repo URL (auto-cloned into a temp dir, discarded afterwards);
- The report is first fully output to the conversation;
- Only after you confirm is it written to the KB at
projects/<repo>/reviews/<topic>-<date>/— remote KB mode only; with the default emptywikiVault.baseUrl(local mode) no wiki page is written.
Read-only in practice: bash/run_code writes and wiki writes outside the reviews namespace are blocked by the guard, while the fs write/edit tools are not blocked in a standalone DT session.
Configuration notes
- Mode, provider and model are all chosen on the 「评审引擎(ocr)」 card; the provider/model dropdowns share the same catalog as the model chain;
- After picking, click 「应用到 ocr」 (Apply to ocr) — the system writes the wiring into ocr's custom config (
dsh-managed); the API key is resolved from the dsh model config and written into ocr, never shown in plain text in the panel; if resolution fails it degrades gracefully and points you to a manualocr config providerin a terminal; - When managed is not ready, the ocr tool refuses the managed call and returns delegate guidance; the reviewer switches to delegate mode — nothing is blocked.
Official docs: Installation · Model configuration · Delegate mode
Trust & guardrails (user's view)
- Read-only hard gate for the lead — in swarm mode, main-session writes to sources and git mutations are blocked by a system gate; if blocked, just let the lead explain — execution is done by the D role.
- Confirmation gate — the lead only builds a chain after you reply with an explicit affirmative (enforced by the lead's instructions, not by a code-level check).
- TDD hard gate — implementations must ship with tests (or an explained skip); reviews machine-verify "tests really ran, and were written first".
- Human trust anchors — spec approval, unblock, audit confirmation and chain deletion are human-only; role agents cannot approve specs, and a chain is only created from your confirmed routing call (the main session routes as
human). - Guardrails are constraints, not a sandbox — PT/DT write guards rely on path and command regexes (reviewers get no git credentials), and review evidence is existence-checked: fields must be present and well-formed, while replaying the commands to prove they ran happens only when
evidenceReplay.enabledis turned on. - Full mechanics (permission matrix, delivery contract, review chain, rework, failure recovery) live under Advanced / Developers.
Advanced / Developers
Mechanics and implementation details below — regular users can skip.
Roles & the execution pipeline (full table)
Six roles are dispatched by the scheduler as one-shot agent sessions (deterministic session id kbn-<taskId>; a retry resumes that same session — resumeSessionId is always null in the current implementation — while a rework task starts its own kbn-<reworkId> session). Each role-agent session is bound to exactly one task (boundTaskId) and gets a trimmed tool face. V is the exception: a chain-scoped orchestrator session (kbn-v-<chainId>) with no boundTaskId.
| Role | Alias | Responsibility | Tool face (highlights) |
|---|---|---|---|
| V | Orchestrator | Drives the phase machine, creates one card per phase, posts [blocked-review] guidance on stalls. Never executes. |
kanban_create + task tools + spec view |
| P | Planner | Reads spec + repo facts (incl. read-only self-checks), writes an OpenSpec implementation plan, opts into PT via pt_decision.needed. Never executes. |
Task tools + spec view, read-only (writes only openspec/changes/) |
| PT | Plan reviewer | Read-only review of P's plan (requirements alignment, completeness, logic). Outputs verdict + issues. | Task tools + spec view, read-only ToolGuard |
| W | Knowledge officer | W2/W3 KB sync (w:kb). Never touches code/git. |
Task tools + wiki_search/read/write (remote) / skill→llm-wiki (local) + prefetch_file/prefetch_external/prefetch_kb + read-only spec view |
| D | Executor | The only role that writes code: worktree → implement → verify → [AI-GEN] commit → push feature branch (merging into the spec-declared target branch is done by the system only after DT passes). |
Task tools + wiki read + bash/fs/run_code (full dev) + subagent (spawn/fork/list-agents) + goal |
| DT | Implementation reviewer | Empirically verifies D's work (test/build/typecheck/diff/git + open-code-review), writes review page to KB. Read-only against the repo. | Task tools + wiki read/write (review namespace) + ocr_review + bash/fs/run_code, read-only ToolGuard |
Guardrails in detail
Permission matrix
can(action, actor, task, { boundTaskId }) in src/domain/permissions.ts.
"Bound" means the actor is the role agent session spawned for that exact task
(boundTaskId === task.id and, for complete, also actor === task.assignee).
| Action | V | P | W | D | PT | DT | Human | System |
|---|---|---|---|---|---|---|---|---|
| create-chain / create-task | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ |
| claim | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ |
| complete | ❌ | bound | bound | bound | bound | bound | ✅ (GUI) | ✅ |
| block | ❌ | bound | bound | bound | bound | bound | ✅ | ✅ |
| heartbeat | ❌ | bound | bound | bound | bound | bound | ❌ | ❌ |
| comment | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| unblock | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ |
| archive | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ |
| spec-approve | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ |
| spec-edit | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ |
| spec-attach | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ |
| update-title | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ |
| delete-chain | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ |
| wiki-write | ❌ | ❌ | ✅ | ❌ | ❌ | ✅ (review ns) | ❌ | ❌ |
| wiki-read | ❌ | ❌ | ✅ | ✅ | ❌ | ✅ | ❌ | ❌ |
| prefetch | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| audit-confirm | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ |
| create-rework-task | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ |
| reopen-chain | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ |
| waive-review | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ |
Key guarantees (two):
- The main session cannot execute. Its kanban tool face is a read-only subset —
kanban_show/kanban_chain/kanban_list/kanban_commentplus the human-recovery pairkanban_reopen_chain/kanban_waive_review— together withspec_card_view,kanban_route, theplanning_*tools andsms_send; neverkanban_create/kanban_complete/kanban_block. Chains/specs are created only via swarm-mode intents or/plan:+/openspec:; the GUI observes and mutates task state but never creates chains or tasks — "who decided to run what" stays explicit and auditable. - Session binding prevents cross-task escalation (a W agent bound to task A
cannot complete/block task B even though both are W tasks); DT writes are
confined to the
projects/<repoSlug>/<chain>/review/namespace by a ToolGuard on top of the matrix; and no role agent can approve specs, unblock, confirm audits, waive a review or reopen a chain — those are human trust anchors;systemhandles only mechanical bookkeeping.
Delivery contract (upstream owes downstream)
Each phase's handoff must carry the keys its downstream actually reads
(src/domain/delivery-contract.ts). Missing delivery keys block the W/P card
immediately and admit no human exemption; the D/PT/DT evidence gates instead reject
complete with an error (the card stays running) and are human-exempt. The
orchestrator never builds a downstream card on a blocked parent:
| Card | Required handoff keys |
|---|---|
W2 / W3 (w:kb) |
kb_url + page_path — non-empty is not enough: with a configured wikiVault.baseUrl the kb_url must start with it (and must be exactly '' in local mode), while page_path must sit in the allowlisted namespaces (wiki/** locally) |
P (p:openspec) |
artifacts_path + pt_decision (needed boolean required; when needed: true, reason is required) |
D (d:execute) |
changed_files + (commit_hash or push) — hasDeliveryEvidence; branch (feature branch) is not a delivery key, but when the TDD gate actually runs the tests it checks the branch and bounces the card if it is absent or mismatched; tdd (test_files or skipped.reason, XOR) |
| PT / DT | review_evidence (schema-valid) — validateReviewEvidence |
TDD hard gate (evidence threshold)
D completes only with tdd — test_files (with test_first) or skipped.reason
(XOR, delivery-evidence.ts). DT's review_evidence must carry tdd; whenever
tdd.test_files are declared the runner must be vitest (test.runner), and on a
pass verdict test_first === true must hold (review-evidence.ts). This makes
"tests actually ran, and were written first" a machine-checked property rather than
a claim.
Gate skip alarm & declaration cross-check
A declaration that disagrees with the diff no longer passes the gate silently
(three silent-skip modes remain, emitting no event: gates.enabled=false, a handoff
without worktree_dir, and non-d:execute cards):
task/gate-skippedevent — a declaredtdd.skippedis allowed when the diff is pure docs/config, or when the diff cannot be computed (conservative alarm-skip); both leave the event as an audit trail. Otherwise the gate bounces the card back (same session, agent fixes and re-completes).- Declaration ↔ reality cross-check — declaring
test_fileswith no test-file change in the diff (stale-test handoff), an emptytest_files, an invalid path, or a branch mismatch all bounce instead of silently skipping. - After 3 cumulative bounces the task is blocked for human review (
gave_up: gate bounced 3 times). - Gate runs now archive raw output to
<storageDir>/gate-logs/<taskId>.log(path is referenced in the gate event detail). review_evidence.lintmust be a structured object (aligning withbuild/typecheck);null/scalars are rejected.
Issue evidence check (PR2, opt-in)
Reviewer-reported issues (DT cards only — PT issues are never evidence-checked) can carry evidence = { file, command, exit } (raw output archive, first line [exit code: N]). Verification is three-tier: missing evidence → flagged (not-provided; critical/high → could-not-replay + needs-human); archive paper-check (zero execution) → matches; on mismatch a replay re-runs the command — only if evidenceReplay.enabled is turned on, and only for allowlisted tool prefixes (word-boundary match; npm run restricted to fixed script names). Replays execute model-written commands and are NOT a sandbox; keep the switch off unless you accept that risk. Results are summarized in a review/evidence-check event; differs never auto-fails a review — it surfaces to human review.
Phase-0 planning checklist
Planning runs a read-only planning session (grill-me → planning_prefetch →
planning_checklist_save, planning-driver.ts). The checklist carries a structured
manifest (repo facts + file baseline, prefetch-manifest.ts); an invalid manifest
blocks the save, and chain creation mounts the checklist as the file-prefetch +
kb attachments on the spec card (prefix-router.ts).
Review quality chain
More in Agents, Automation & Workflows
archify
by tt-a1i
Agent skill for beautiful, verifiable architecture, workflow, sequence, data-flow, and lifecycle diagrams—self-contained HTML with motion and crisp export.
openviking
by volcengine
Self-evolving Context Database for AI Agents. Unify Agent Memory, Knowledge RAG and Skills.
nocobase
by nocobase
NocoBase is an open-source AI + no-code platform for building business systems fast. Instead of generating everything from scratch, AI works on top of production-proven infrastructure and a WYSIWYG no-code interface, so you get both speed and reliability.
learn-harness-engineering
by walkinglabs
Harness engineering beginner tutorial, from 0 to 1
