# dsh-work-crew dsh-work-crew — one prompt, a working team

version license platform workers

One prompt. A working team.
一个指令。一支有纪律的本机 AI 班组。

简体中文 · English

--- `dsh-work-crew` is a [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) plugin that turns the AI apps already installed on your machine — Doubao, WorkBuddy, ZCode, Qoder — into a **crew with a task board**. DSH stays the orchestrator. It does not write your code itself; it plans, dispatches, enforces locks, collects receipts and keeps the books. The crew does the typing. ## Why One model reviewing its own work is the weakest link in every AI coding session: | Failure | What the crew does instead | |---|---| | **Self-review blind spot** — the model checks its own output | A different model reviews it; the implementer never signs off on itself | | **Concurrent edits** — writing and reviewing the same file at once | Artifact locks: `write:landing:hero` and `read:landing` cannot overlap in time | | **Lost progress** — who is waiting for whom, asked again next session | A task board on disk (`.dsh-team/`) with dependencies, locks and timeline | ## Install ```powershell # from GitHub dsh plugin --profile desktop add github:yxyusage/dsh-work-crew # from a local checkout dsh plugin --profile desktop add "E:\path\to\dsh-work-crew" ``` Then fully quit DSH (tray → Quit) and reopen it. ## Quick start ```text team_init → create .dsh-team/ (mission, roles, board, outbox) team_add_task → title, worker, dependsOn, write/read locks, expect team_dispatch → builds a brief, enforces locks, sends it (queues when busy) team_collect → wait for receipts; takes taskIds, returns whoever finishes first team_status → board: who is running, what is queued, which locks are held ``` A typical plan: ``` T1 implement hero WorkBuddy write:landing:hero T2 review landing Doubao read:landing ← waits for T1 (write×read) T3 product discussion Doubao — ← runs in parallel with T1 T4 docs Qoder write:docs dependsOn: [T1, T2] ``` ## Tools | Tool | When to use | |---|---| | `team_init` | first time in a project; records reference dirs and required docs | | `team_status` | who runs what, queue depth, last activity, held locks | | `team_add_task` | declare worker, dependencies, locks, deadline, expected artifacts | | `team_dispatch` | send a brief; **takes `taskIds` to dispatch several in one step**; queues when a worker is busy | | `team_collect` | wait for receipts: `taskIds` returns whoever finishes first | | `team_reassign` | move a task to another worker, keeping brief and history | | `team_reopen` | a false completion → back to running, without re-sending | | `team_resubmit` | artifacts now exist → re-check expect instead of re-dispatching | | `team_release` | close a task (refuses `done` while expected artifacts are missing) | | `team_split_html` | split a single-file page into html/css/js so three workers can edit in parallel | | `team_shot` | screenshot to a file, path only — device emulation for mobile widths | | `team_workers` | status / preflight / restart / ping | ## Workers | id | App | Good at | Debug port | |---|---|---|---| | `workbuddy` | WorkBuddy | implementing, running commands, verifying builds | 9332 | | `doubao` | Doubao | visual review, ideas, reading screenshots | 9331 | | `zcode` | ZCode | implementation / second opinion (limited free quota) | 9334 | | `qoder` | Qoder | implementation / read-only audits (VS Code family) | 9335 | ## How it works - **Driven over CDP.** The plugin launches each app with `--remote-debugging-port` and types into its chat box. Windows can stay offscreen; nothing steals your mouse. - **Completion is a hard signal.** WorkBuddy's "已完成" badge; Doubao/ZCode/Qoder's `@@END@@` sentinel. No guessing from text stillness. - **File handoff.** Workers write reports to `.dsh-team/outbox/.md` and reply with one line. The body never enters the orchestrator's context — that is where the token savings come from. - **Locks with hierarchy.** `landing` covers `landing:hero`; siblings (`hero`, `meta`) run in parallel. - **Queue, not stuck.** A busy worker queues the task (`queued`, no locks, no timeout) and promotes it when the current one is collected. - **Budget.** `deadlineMin` (default 45) flags a stalled task; at twice the budget it is blocked and its locks released. - **Artifacts are checked.** `expect` paths must exist before a task counts as done; the outbox file is added automatically. ## Screenshots: two traps that produce false reviews Use `team_shot` — it already avoids both traps and returns only a path: ```text team_shot { "target": "index.html", "out": "shots/mobile-390.png", "width": 390, "mobile": true } ``` **Trap 1 — capturing mid-animation.** A headless shot without a virtual clock lands on the fade-in, so the page looks half-transparent. `team_shot` emulates `prefers-reduced-motion: reduce` and waits for the layout to settle. **Trap 2 — resizing the window instead of emulating the device.** `--window-size=390,844` sets the *window*, but the layout keeps the desktop viewport (~980px), so the shot is a cropped desktop page. That reads as "the layout overflows" and sends a reviewer chasing a bug that does not exist. Device emulation is the only honest mobile shot, and `team_shot` checks `scrollWidth` for you: if it equals the viewport, the layout is fine. ## Guardrails Six checks stand between "the model says it is done" and "the task is done": | Guard | What it does | |---|---| | `review: true` | The reviewer gets **requirement + `git diff` + rubric only**. It is told not to read the implementer's report — a reviewer that inherits the author's narrative inherits the author's blind spots. | | Snapshot review | The changed files are copied to `.dsh-team/snapshots//` and the reviewer reads **the copy**, so the review takes no read lock and the next implementation starts immediately. Diffing starts from the implementer's recorded `baseCommit`, so committed work still shows up. | | `verify: "pnpm build"` | The acceptance command runs in the project before the task may close. A red build blocks the task; no green build, no done. | | `risk: "high"` | High-risk work (auth, payments, CI, secrets, installers) **never self-approves**: collecting it only reports "awaiting approval" until a human re-collects with `confirm: true`. | | `rubric.md` + review round counter | `team_init` writes the project's acceptance rubric; every review carries it. From the 4th review of the same artifact, the brief asks whether the *plan* is wrong instead of requesting another patch list. | | `crossCheck: true` | After a review, a **second reviewer** gets the findings and votes on each one: holds / false positive / not enough evidence. Only confirmed issues survive. | ## Knowledge base "Make it look good" produces nothing. "Look at this, apply it like so, ship when these three rules hold" changes the output. `team_knowledge` ships curated references; the matching ones are injected into the brief automatically — authors do not have to remember to ask. | Entry | What it enforces | Source | |---|---|---| | `de-ai-slop` | no purple gradients, no three-card hero, no emoji icons, real content instead of filler | [anti-slop checklist](https://github.com/infometa/workbuddyskills/blob/main/experts/design-engine/skills/quality-review/references/anti-slop-checklist.md) | | `frontend-ui` | component structure and the four states (default/hover/focus/disabled) | [shadcn AI Elements](https://ui.shadcn.com/docs/ai-elements) | | `motion` | shared-element transitions, 120–360 ms, transform/opacity only, reduced-motion fallback | [smooth-option-switcher](https://github.com/zhoulinhua0-star/smooth-option-switcher) | | `empty-states` | why it is empty, what to do now, what you will get | [Carbon patterns](https://www.carbondesignsystem.com/building-blocks/core/patterns/empty-states) | | `typography-color` | modular scale, 16–18px body, 4.5:1 contrast, no pure black | [type-scale](https://type-scale.com) | | `copywriting` | verbs on buttons, examples instead of adjectives, no judgement | [NN/g microcopy](https://www.nngroup.com/articles/microcopy/) | | `a11y` | keyboard path, visible focus, button semantics | [web.dev a11y](https://web.dev/learn/accessibility) | Beyond the interface, the same mechanism covers backend and review work: | Entry | What it enforces | Source | |---|---|---| | `api-design` | plural resources, RFC 9457 errors, idempotent writes | [Google AIP](https://google.aip.dev/) | | `backend-patterns` | 12-factor, when splitting a service is justified | [microservices.io](https://microservices.io/patterns/index.html) | | `sql-data` | index by query, read the plan before touching indexes | [use-the-index-luke](https://use-the-index-luke.com/) | | `testing` | test pyramid, regression test per bug | [Fowler](https://martinfowler.com/articles/practical-test-pyramid.html) | | `code-review` | five things to look at, two grades of comment | [Google eng-practices](https://google.github.io/eng-practices/review/) | | `security` | server-side validation, auth at every entry, secrets out of logs | [OWASP Top 10](https://owasp.org/www-project-top-ten/) | | `observability` | structured logs, metrics, actionable alerts | [OpenTelemetry](https://opentelemetry.io/docs/) | | `technical-writing` | one page, one purpose (tutorial/how-to/reference/explanation) | [Diátaxis](https://diataxis.fr/) | | `web-performance` | measure first: LCP/INP/CLS | [HPBN](https://hpbn.co/) | Matching: explicit `tags` on the task win; otherwise keywords in the title and brief decide. **The worker matters too** — Doubao is held to design/motion, Qoder to security/structure, ZCode to copy/docs, WorkBuddy to implementation. At most 4 entries, each rendered as link + how to use + what not to do + 3 rules. And the loop closes at review time: a review task receives **the checklist the implementer was given**, up to 8 rules, each to be judged `done / not done (with location) / not applicable`. That turns "check it" into findings you can act on. Project-specific entries go in `.dsh-team/knowledge/.md` and override built-ins by id: ```text team_knowledge { "action": "add", "id": "brand-guide", "title": "品牌规范", "tags": ["frontend","color"], "url": "https://...", "use": "配色只从这 5 个色里选", "avoid": "自创渐变", "rules": ["主色 #1f6feb,只用于主按钮", "正文色 #0f1115 / #e6e8eb"] } ``` ## Workflow ```mermaid flowchart TB A["team_add_task
tags · locks · expect · verify · risk"] --> B{"能否并行?
不同文件 / 不同 worker"} B -- 是 --> C["team_dispatch taskIds
一次派多个"] B -- 否 --> D["team_dispatch"] C --> E["简报 = 需求 + diff + 参考资料 + 对照清单"] D --> E E --> F["worker 干活
正文写 outbox/<id>.md · 聊天只回 DONE"] F --> G{"收单闸门"} G -- 控制台报错 / 溢出 --> H["blocked 打回"] G -- expect 缺失 --> H G -- verify 命令失败 --> H G -- 知识库机械规则 --> H G -- 全部通过 --> I["评审:快照 + 对照清单逐条判"] I --> J{"通过?"} J -- 否 --> K["修复任务
按文件并行"] K --> F J -- 是 --> L["team_bundle 合并单文件
自动复检"] L --> M["交付"] ``` Four gates stand between "the model says done" and done: **artifacts exist** (`expect`), **the build passes** (`verify`), **the page actually runs** (console errors + overflow + mechanical gates), and **a reviewer judges the same checklist the implementer was given**. Any failure blocks the task instead of passing it downstream. ## Token economics Measured on a real run (18 tasks, one landing page). Method: UTF-8 3 bytes per Chinese character, 1 token ≈ 1.5 characters. | Quantity | Measured | Why it matters | |---|---|---| | Worker output kept on disk | **115,188 bytes** in 17 outbox files ≈ 25.6k tokens | With chat delivery this enters the orchestrator's context and is re-sent on **every** later step | | Briefs sent to workers | 57,864 bytes ≈ 12.9k tokens | Sent over CDP straight into the apps — never touches the orchestrator's context | | Average single output | 6,776 bytes ≈ 1.5k tokens | One read costs more than the whole dispatch brief | | Dispatch calls | 8 calls for 18 tasks (`taskIds` batch) | ~10 fewer steps than one call per task | | Collect calls | 10 calls for 18 tasks (`taskIds` batch) | Whoever finishes first returns; no polling loop | | Restarts | 1 call for four apps (`restart all`) | Was 4 steps, each re-sending the conversation | | Screenshots | path only, image never read | Each image read costs ~1–2k tokens and stays in context | The arithmetic that matters: a step costs *context size × 1*. Keeping 25.6k tokens of worker prose out of the context saves that amount on every subsequent step. Over a 40-step run that is roughly **a million token-equivalents of context traffic** that never happens (mostly cache reads — cheap, but not free). What it costs: each dispatch carries ~800 bytes of references plus a ~2k-token checklist to the worker. That is paid to the worker's API, not to the orchestrator. ## Requirements - Windows with DSH Desktop (or DSH Web + Node 22+). - At least one of the four apps installed and **logged in**. - In each app: select the project folder as its workspace, and allow auto-approval / full access. - The plugin launches the apps itself; an app already running without a debug port must be restarted (`team_workers {"action":"restart","worker":"doubao"}`), which is also the fix when a port goes stale. ## Limits - Selectors are tied to each app's UI. App updates can break them; every worker carries a `spec` version and `team_workers {"action":"ping"}` tells you whether the chain still works. - Quota cannot be read from any of the four apps. A worker that runs out mid-task is detected by timeout and is meant to be re-dispatched with `team_reassign`. - One app can hold only one in-flight task. That is a property of a single input channel, not a bug. - Kimi desktop is not supported: it rejects both `--remote-debugging-port` and `--remote-debugging-pipe`. ## Layout ``` index.js tools + the /dsh-work-crew/state route for the panel lib/team.js board, locks, briefs, roles, queue lib/cdp.js CDP sessions, launch, typing, reading, completion rules client.js sidebar panel (React, conversation.composer.dock) locale/ zh + en metadata ``` ## License MIT