# ЁЯзк dsh-test-drive
- **1024 рд╕реНрдЯреЛрд░ рдЪреИрдирд▓**: рдПрдХ рдмрд╛рд░ `npm i -g dsh1024`, рдлрд┐рд░ `dsh1024 plugin --profile web add dsh-test-drive` ([deepseek1024.com](https://deepseek1024.com) рдЗрдВрд╕реНрдЯреЙрд▓ рд░реИрдВрдХрд┐рдВрдЧ рдореЗрдВ рдЧрд┐рдирд╛ рдЬрд╛рддрд╛ рд╣реИ)ред
**DeepSeek Harness рдкреНрд▓рдЧрдЗрди рдХреЗ рд▓рд┐рдП рдкреГрдердХ рдЗрдВрд╕реНрдЯреЙрд▓-рдФрд░-рд╕реНрдореЛрдХ рдкрд░реАрдХреНрд╖рдгред**
*рдПрдХ рдбрд┐рд╕реНрдкреЛрдЬрд╝реЗрдмрд▓ рдкреНрд░реЛрдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдЗрдВрд╕реНрдЯреЙрд▓, рд╕реНрдореЛрдХ, рд╕рддреНрдпрд╛рдкрди рдФрд░ рд╕рдлрд╝рд╛рдИ рдХрд░реЗрдВ тАФ рдЖрдкрдХрд╛ рдЕрд╕рд▓реА `~/.dsh` рдЕрдЫреВрддрд╛ рд░рд╣рддрд╛ рд╣реИред*
[](LICENSE)
[](https://gitee.com/perrylink/dsh-test-drive)
[](https://github.com/topics/dsh-plugin)
[](https://github.com/PerryLink/dsh-plugin-doctor#verified-х╛╜чла)
[](https://dsh.market/)
[](#)
[](https://github.com/PerryLink/dsh-test-drive/actions)
[](https://github.com/PerryLink/dsh-test-drive/releases)
[](https://www.npmjs.com/package/dsh-test-drive)
[](https://www.npmjs.com/package/dsh-test-drive)
[English](README.md) ┬╖ [чоАф╜Уф╕нцЦЗ](README-zh.md) ┬╖ [Espa├▒ol](README-es.md) ┬╖ [Portugu├кs](README-pt.md) ┬╖ [рд╣рд┐рдиреНрджреА](README-hi.md)
```sh
dsh plugin --profile add dsh-test-drive
```
---
**ЁЯУЦ рдЗрдХреЛрд╕рд┐рд╕реНрдЯрдо рдиреЙрд▓реЗрдЬ рдмреЗрд╕** тАФ рдорд╛рдкреЗ рдЧрдП рдЖрдБрдХрдбрд╝реЗ, рдорд╛рд░реНрдХреЗрдЯрд┐рдВрдЧ рдирд╣реАрдВ: [рдбреЗрд╡рд▓рдкрдореЗрдВрдЯ рдЧрд╛рдЗрдб ┬╖ рдЪрдпрди рдбреЗрдЯрд╛ ┬╖ рд░рдЦрд░рдЦрд╛рд╡ рдорд╛рдирджрдВрдб](https://perrylink.github.io/dsh-plugin-guide/)ред
## Install & uninstall (рдЗрдВрд╕реНрдЯреЙрд▓ рдФрд░ рдЕрдирдЗрдВрд╕реНрдЯреЙрд▓)
```sh
dsh plugin --profile web add dsh-test-drive # рдЗрдВрд╕реНрдЯреЙрд▓ (npm) тАФ рдпрд╛ рдКрдкрд░ рд╡рд╛рд▓рд╛ git рд░реВрдк
dsh plugin --profile web remove dsh-test-drive # рдЕрдирдЗрдВрд╕реНрдЯреЙрд▓
```
## тнР хжВцЮЬхоГх╕охИ░ф║Жф╜а
рдпрд╣ рдкреНрд▓рдЧрдЗрди [DSH рдкреНрд▓рдЧрдЗрди рдкрд░рд┐рд╡рд╛рд░](https://github.com/PerryLink) рдХрд╛ рд╣рд┐рд╕реНрд╕рд╛ рд╣реИ (95 рдкреНрд▓рдЧрдЗрди, рд╕рднреА Apache-2.0)ред рдЕрдЧрд░ рдпрд╣ рдЙрдкрдпреЛрдЧреА рд▓рдЧреЗ, рддреЛ **рдПрдХ рд╕реНрдЯрд╛рд░ рджреЗрдВ** тАФ рдЗрд╕рд╕реЗ рдХреЛрдИ рд╕реБрд╡рд┐рдзрд╛ рдЕрдирд▓реЙрдХ рдирд╣реАрдВ рд╣реЛрддреА, рдкрд░ рдЕрдЧрд▓рд╛ рд╡реНрдпрдХреНрддрд┐ рдЗрд╕реЗ рдЦреЛрдЬ рдореЗрдВ рдЖрд╕рд╛рдиреА рд╕реЗ рдкрд╛ рд▓реЗрддрд╛ рд╣реИред
*English:* part of a 95 plugin family for DeepSeek Harness. If it is useful, **a star helps the next person find it** тАФ nothing is gated behind it.
## What is dsh-test-drive?
DeepSeek Harness рдкреНрд▓рдЧрдЗрди рдХреЗ рд▓рд┐рдП рдкреГрдердХ рдЗрдВрд╕реНрдЯреЙрд▓-рдФрд░-рд╕реНрдореЛрдХ рдкрд░реАрдХреНрд╖рдгред
рдПрдХ рдбрд┐рд╕реНрдкреЛрдЬрд╝реЗрдмрд▓ рдкреНрд░реЛрдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдЗрдВрд╕реНрдЯреЙрд▓, рд╕реНрдореЛрдХ, рд╕рддреНрдпрд╛рдкрди рдФрд░ рд╕рдлрд╝рд╛рдИ рдХрд░реЗрдВ тАФ рдЖрдкрдХрд╛ рдЕрд╕рд▓реА `~/.dsh` рдЕрдЫреВрддрд╛ рд░рд╣рддрд╛ рд╣реИред

*рдХрд╛рд░реНрдпрдкреНрд░рд╡рд╛рд╣: рдкреНрд░рд╢реНрди тЖТ рд╕реАрд▓рдмрдВрдж рд╕реНрд░реЛрдд тЖТ рд░рд┐рдкреЛрд░реНрдЯред рдиреАрдЪреЗ рдХреЗ рдЙрджрд╛рд╣рд░рдг рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдХрдорд╛рдВрдб рд╕рддрд╣ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред*
*рд╡рд╣реА рд░рди, рдПрдирд┐рдореЗрдЯреЗрдбред*
## Compatibility (рд╕рдВрдЧрддрддрд╛)
| рдШрдЯрдХ | рд╕рдВрд╕реНрдХрд░рдг |
|---|---|
| DeepSeek Harness | **`dsh-v0.2.1-alpha.1`** (GitHub tag, 2026-09-11 рдХреЛ рд╕рддреНрдпрд╛рдкрд┐рдд: рдкреВрд░реНрдг рдЧреЗрдЯ рд╢реНрд░реГрдВрдЦрд▓рд╛ + рдкреНрд░реЛрдлрд╝рд╛рдЗрд▓ рдЗрдВрд╕реНрдЯреЙрд▓ рд╕реНрдореЛрдХ)ред npm рдирд┐рд░реНрднрд░рддрд╛ рд▓рд╛рдЗрди `0.1.2-rc.1` рдФрд░ `0.1.7-rc.2` (peer рдирд┐рд░реНрднрд░рддрд╛рдПрдБ `>=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0`)уАВ |
| Node.js | `^22.19.0 \|\| >=24.0.0` |
| рдкреИрдХреЗрдЬ рдкреНрд░рдмрдВрдзрдХ | `pnpm@11.7.0` |
| рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо | Windows / macOS / Linux (рдХреЗрд╡рд▓ host рдкреНрд▓рдЧрдЗрди) |
| рдмрд╛рд╣рд░реА рдЙрдкрдХрд░рдг | PATH рдкрд░ `dsh` CLI (рд╕реНрд╡рддрдГ-рдкрд╣рдЪрд╛рди, npm shim рдкрд╛рд░реНрд╕ рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВ), PATH рдкрд░ `pnpm` |
## What you get (рдЖрдкрдХреЛ рдХреНрдпрд╛ рдорд┐рд▓рддрд╛ рд╣реИ)
- `test_drive` рдЙрдкрдХрд░рдг тАФ рдПрдХ рд▓рдХреНрд╖реНрдп рдХреЛ рдкреВрд░реА рдкрд╛рдЗрдкрд▓рд╛рдЗрди рд╕реЗ рдЧреБрдЬрд╝рд╛рд░рддрд╛ рд╣реИ: `dsh plugin add` тЖТ `--dump-config` рдкреИрдЪ рдЬрд╛рдБрдЪ тЖТ рд╣реЗрдбрд▓реЗрд╕ рдмреВрдЯ рд╕реНрдореЛрдХ (FAILED рдорд╛рд░реНрдХрд░ рд╕реНрдХреИрди + рд╡реИрдХрд▓реНрдкрд┐рдХ рдПрдХ-рд╡рд╛рдХреНрдп рдХрд╛рд░реНрдп) тЖТ рд╡реИрдХрд▓реНрдкрд┐рдХ рдХреНрд╖рдорддрд╛-рдкреБрд╖реНрдЯрд┐ тЖТ `dsh plugin remove` тЖТ рдХреНрд╡рд╛рд░рдВрдЯреАрди рд╕рдлрд╝рд╛рдИред рд╕рдВрд░рдЪрд┐рдд рд░рд┐рдХреЙрд░реНрдб рд╕рдордХрд╛рд▓рд┐рдХ рд░реВрдк рд╕реЗ рд▓реМрдЯрд╛рддрд╛ рд╣реИ, рдпрд╛ `background: true` рдкрд░ `{ kind: 'background', jobId }`ред
- `/testdrive` рдХрдорд╛рдВрдб тАФ рд╕реНрдкреЗрд╕/рдХреЙрдорд╛ рд╕реЗ рдЕрд▓рдЧ рдХрд┐рдП рдЧрдП рд▓рдХреНрд╖реНрдпреЛрдВ рдХреА рд╕реВрдЪреА рдХреЛ `ctx.jobs` рдкрд░ `drive-batch` рдкреГрд╖реНрдарднреВрдорд┐ рдХрд╛рд░реНрдп рдХреЗ рд░реВрдк рдореЗрдВ рдЪрд▓рд╛рдХрд░ рдореИрдЯреНрд░рд┐рдХреНрд╕ рд░рд┐рдкреЛрд░реНрдЯ (JSON + Markdown) рдмрдирд╛рддрд╛ рд╣реИред
- `drive_report` рдЙрдкрдХрд░рдг тАФ рдХрд┐рд╕реА рднреА рд░рди (`tdr_...`), рдореИрдЯреНрд░рд┐рдХреНрд╕ (`tdm_...`) рдпрд╛ рдирд╡реАрдирддрдо рдореИрдЯреНрд░рд┐рдХреНрд╕ рдХреЛ рд▓рд╛рддрд╛ рд╣реИ; Markdown рдореЗрдВ рдкреНрд░рд╕реНрддреБрдд рд╣реЛрддрд╛ рд╣реИред
- рдХреНрд╖рдорддрд╛-рдкреБрд╖реНрдЯрд┐ тАФ тАЬрдмреВрдЯ рд╣реБрдЖ рдФрд░ рдмрд╛рд╣рд░ рдирд┐рдХрд▓рд╛тАЭ рд╕реЗ рдЖрдЧреЗ: рд╡реИрдХрд▓реНрдкрд┐рдХ `capability` рдЪрд░рдг рдПрдЬреЗрдВрдЯ рд╕реЗ рдирд╛рдорд┐рдд рдЙрдкрдХрд░рдг рдХреЛ рдмреБрд▓рд╡рд╛рддрд╛ рд╣реИ (рдпрд╛ `/command` рдЪрд▓рд╡рд╛рддрд╛ рд╣реИ) рдФрд░ рдЯрд┐рдХрд╛рдК рд╕рддреНрд░ рд▓реЙрдЧ рдореЗрдВ рдЖрд╣реНрд╡рд╛рди рддрдерд╛ `expect` рд╡рд╛рд▓рд╛ рдкреНрд░реЗрдХреНрд╖рд┐рдд рдЖрдЙрдЯрдкреБрдЯ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░рддрд╛ рд╣реИред рд╕рд╛рдлрд╝ рдмреВрдЯ рдХреЗрд╡рд▓ рд╕реНрдореЛрдХ рдЯреЗрд╕реНрдЯ рд╣реИ; `observed` рд╕рд┐рджреНрдз рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдирд╛рдорд┐рдд рдХреНрд╖рдорддрд╛ рд╕рдЪрдореБрдЪ рдХрд╛рдо рдХрд░рддреА рд╣реИред
- рд╕рдВрд░рдЪрд┐рдд рдкрд░рд┐рдгрд╛рдо тАФ рд╣рд░ рд░рд┐рдХреЙрд░реНрдб рдореЗрдВ рд╡рд┐рднреЗрджрдХ `schema: "dsh-test-drive/v1"` рдФрд░ рдкреНрд░рдердо-рд╢реНрд░реЗрдгреА рдлрд╝реАрд▓реНрдб рд╣реЛрддреЗ рд╣реИрдВ: `stages.install.status` (`pass`/`fail`), `stages.smoke.status` (`pass`/`fail`/`boot-ok`/`skipped`), рдкреНрд░рддрд┐-рдЪрд░рдг `durationMs`, рд╕реИрдирд┐рдЯрд╛рдЗрдЬрд╝ рдХрд┐рдП рдЧрдП `summary`/`outputTail`, рдФрд░ рд╕рдордЧреНрд░ `verdict` (`pass`/`fail`/`partial`/`unknown`)ред рдпрд╣реА рдорд╢реАрди-рдкрдардиреАрдп рдЕрдиреБрдмрдВрдз рд╣реИ рдЬрд┐рд╕реЗ рд╕реНрдХреЛрд░рд┐рдВрдЧ рдкрд╛рдЗрдкрд▓рд╛рдЗрдиреЗрдВ (dsh-score) рдЙрдкрднреЛрдЧ рдХрд░рддреА рд╣реИрдВред
- рдирд┐рд░реНрдорд╛рдг рд╕реЗ рд╕реБрд░рдХреНрд╖рд╛ тАФ рд╣рд░ рдЕрд╕реНрдерд╛рдпреА рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдЗрд╕ рдкреНрд▓рдЧрдЗрди рджреНрд╡рд╛рд░рд╛ рд╕рдорд░реНрдкрд┐рдд рдЙрдкрд╕рд░реНрдЧ `dsh-test-drive-` рдХреЗ рддрд╣рдд рдмрдирд╛рдИ рдЬрд╛рддреА рд╣реИ, рдПрдХ рд╕рдХреНрд░рд┐рдп рд╕реНрд╡рд╛рдорд┐рддреНрд╡ рд░рдЬрд┐рд╕реНрдЯреНрд░реА рдореЗрдВ рджрд░реНрдЬ рд╣реЛрддреА рд╣реИ, рдФрд░ рдХреЗрд╡рд▓ dry-run тЖТ рдХреНрд╡рд╛рд░рдВрдЯреАрди-рдирд╛рдорд╛рдВрддрд░рдг тЖТ рд╣рдЯрд╛рдиреЗ рдХреА рд╕реАрдврд╝реА рд╕реЗ рд╣рдЯрд╛рдИ рдЬрд╛рддреА рд╣реИред рд╣реЛрд╕реНрдЯ рдкреНрд░реЛрдлрд╝рд╛рдЗрд▓ рдХрднреА рдкрдврд╝реА рдпрд╛ рд▓рд┐рдЦреА рдирд╣реАрдВ рдЬрд╛рддреАред
## Quick start (рддреНрд╡рд░рд┐рдд рд╢реБрд░реБрдЖрдд)
### git рдЪреИрдирд▓
```sh
dsh plugin --profile web add github:PerryLink/dsh-test-drive#
```
рдкрд╣рд▓рд╛ `add` рд╡рд┐рдлрд▓ рд╣реЛрддрд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ pnpm рдкреИрдХреЗрдЬ рдХреА `prepare` рдмрд┐рд▓реНрдб рд░реЛрдХрддрд╛ рд╣реИ; pnpm рджреНрд╡рд╛рд░рд╛ рдЫрд╛рдкреА рдЧрдИ рд╕рдЯреАрдХ рдХреБрдВрдЬреА рдХреЛ рдкреНрд░реЛрдлрд╝рд╛рдЗрд▓ рдХреЗ `pnpm-workspace.yaml` рдореЗрдВ рдХреЙрдкреА рдХрд░реЗрдВ рдФрд░ рдлрд┐рд░ рдЪрд▓рд╛рдПрдБ:
```yaml
allowBuilds:
'dsh-test-drive': true
```
### npm рдЪреИрдирд▓
```sh
dsh plugin --profile web add dsh-test-drive
```
рдкрд╣рд▓реЗ рд╕реЗ рдмрдиреЗ рдкреИрдХреЗрдЬреЛрдВ рдХреЛ рдмрд┐рд▓реНрдб рдЕрдиреБрдорддрд┐ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реЛрддреАред рдкреНрд░реЛрдлрд╝рд╛рдЗрд▓ рдкреБрдирдГ рдЖрд░рдВрдн рдХрд░реЗрдВ, рдлрд┐рд░ рд╕рддреНрд░ рд╕реЗ `test_drive` / `/testdrive` рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред
## DSH Desktop рд╕рдорд░реНрдерд┐рдд рдкрд░реАрдХреНрд╖рдг рд╣реЛрд╕реНрдЯ рдирд╣реАрдВ рд╣реИ
`test_drive` рдХреЛ рдРрд╕рд╛ `dsh` CLI рдЪрд╛рд╣рд┐рдП рдЬреЛ **рджреВрд╕рд░рд╛** headless DSH рдкреНрд░реЛрд╕реЗрд╕ рд╢реБрд░реВ рдХрд░ рд╕рдХреЗред
DSH Desktop рдХрд╛ `dsh.CMD` launcher рдХреЗрд╡рд▓ `dsh plugin тАж`, `--dump-config` рдФрд░ `--version`
рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ; рдиреАрддрд┐ рдХреЗ рдХрд╛рд░рдг рд╡рд╣ рджреВрд╕рд░рд╛ headless boot рдЕрд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддрд╛ рд╣реИред
`config.dshBin` рдХреЛ npm/pnpm рд╕реЗ рд╕реНрдерд╛рдкрд┐рдд `dsh` CLI (рдпрд╛ рд╕рд╛рдорд╛рдиреНрдп Node + dsh JS entry) рдкрд░
рд╕реЗрдЯ рдХрд░реЗрдВред рдЕрдм рддреНрд░реБрдЯрд┐ тАЬcannot parse npm shimтАЭ рдХреЗ рдмрдЬрд╛рдп рдпрд╣ рд╕реНрдкрд╖реНрдЯ рдХрд╛рд░рдг рдмрддрд╛рддреА рд╣реИред
## Configuration (рд╡рд┐рдиреНрдпрд╛рд╕)
рд╕рднреА рдХреБрдВрдЬрд┐рдпрд╛рдБ рд╡реИрдХрд▓реНрдкрд┐рдХ рд╣реИрдВ (рдбрд┐рдлрд╝реЙрд▓реНрдЯ рджрд┐рдЦрд╛рдП рдЧрдП); рдЕрдорд╛рдиреНрдп рдорд╛рди рд▓реЛрдб рдХреЗ рд╕рдордп рдЬрд╝реЛрд░ рд╕реЗ рд╡рд┐рдлрд▓ рд╣реЛрддреЗ рд╣реИрдВред
| рдХреБрдВрдЬреА | рдбрд┐рдлрд╝реЙрд▓реНрдЯ | рд╡рд┐рд╡рд░рдг |
|---|---|---|
| `profileName` | `headless` | рд╣рд░ рдбрд┐рд╕реНрдкреЛрдЬрд╝реЗрдмрд▓ DSH_HOME рдореЗрдВ рдЖрд░рдВрдн рдХрд┐рдпрд╛ рдЬрд╛рдиреЗ рд╡рд╛рд▓рд╛ рдкреНрд░реЛрдлрд╝рд╛рдЗрд▓ рдЯреЗрдореНрдкрд▓реЗрдЯ (base + headless рдмрдВрдбрд▓)ред |
| `dshBin` | `""` | dsh рдирд┐рд╖реНрдкрд╛рджрдирдпреЛрдЧреНрдп рдХреЗ рд▓рд┐рдП рдирд┐рд░рдкреЗрдХреНрд╖ рдкрде рдУрд╡рд░рд░рд╛рдЗрдб; рдЦрд╛рд▓реА = PATH рдкрд░ `dsh` рд╕реНрд╡рддрдГ-рдкрд╣рдЪрд╛рдиред |
| `headlessTask` | `"Reply with exactly: ok"` | рдмреВрдЯ-рд╕реНрдореЛрдХ рдЪрд░рдг рдХрд╛ рдПрдХ-рд╡рд╛рдХреНрдп рдХрд╛рд░реНрдп; рдЦрд╛рд▓реА = рдЪрд░рдг рдЫреЛрдбрд╝реЗрдВред |
| `forwardEnv` | `[]` | рдкрд░реАрдХреНрд╖рдг-рдкреНрд░реЛрдлрд╝рд╛рдЗрд▓ рдЙрдк-рдкреНрд░рдХреНрд░рд┐рдпрд╛рдУрдВ рдореЗрдВ рднреЗрдЬреЗ рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ рдкрд░реНрдпрд╛рд╡рд░рдг рдЪрд░реЛрдВ рдХреЗ **рдирд╛рдо** (рдорд╛рди рдХрднреА рдирд╣реАрдВ)ред |
| `allowBuilds` | `true` | рдкрд░реАрдХреНрд╖рдг рдкреНрд░реЛрдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдЕрд╡рд░реБрджреНрдз git `prepare` рдмрд┐рд▓реНрдб рдХреЛ рдЕрдиреБрдорддрд┐ рджреЗрдВ рдФрд░ рдЗрдВрд╕реНрдЯреЙрд▓ рдПрдХ рдмрд╛рд░ рдкреБрдирдГ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВред |
| `installTimeoutMs` | `600000` | `dsh plugin add` рдЪрд░рдг рдХреА рд╕рдордп-рд╕реАрдорд╛ред |
| `configTimeoutMs` | `60000` | `--dump-config` рдЪрд░рдг рдХреА рд╕рдордп-рд╕реАрдорд╛ред |
| `smokeTimeoutMs` | `300000` | рд╣реЗрдбрд▓реЗрд╕ рдмреВрдЯ-рд╕реНрдореЛрдХ рдЪрд░рдг рдХреА рд╕рдордп-рд╕реАрдорд╛ред |
| `capabilityTimeoutMs` | `300000` | рдХреНрд╖рдорддрд╛-рдкреБрд╖реНрдЯрд┐ рдХрд╛рд░реНрдп рдХреА рд╕рдордп-рд╕реАрдорд╛ред
| `capability.enabled` | `false` | рдХреНрд╖рдорддрд╛-рдкреБрд╖реНрдЯрд┐ рдЪрд░рдг рдЪрд▓рд╛рдПрдБ (рдкрдВрдЬреАрдХреГрдд тЖТ рдЖрд╣реВрдд тЖТ рдкреНрд░реЗрдХреНрд╖рд┐рдд)ред
| `capability.kind` | `tool` | рдХреНрдпрд╛ рдЬрд╛рдБрдЪреЗрдВ: `tool` рдпрд╛ `command`ред
| `capability.name` | `""` | рдЙрдкрдХрд░рдг рдпрд╛ рдХрдорд╛рдВрдб рдирд╛рдо (рдЖрдЧреЗ `/` рдХреЗ рдмрд┐рдирд╛)ред
| `capability.args` | `""` | рдЖрд╣реНрд╡рд╛рди рдкрд╛рда: рдЙрдкрдХрд░рдг рддрд░реНрдХ (JSON-рд╢реИрд▓реА) рдпрд╛ рдХрдорд╛рдВрдб рд╢рдмреНрджред
| `capability.expect` | `""` | рдкреНрд░реЗрдХреНрд╖рд┐рдд рдЖрдЙрдЯрдкреБрдЯ рдореЗрдВ рдЕрдкреЗрдХреНрд╖рд┐рдд рдЕрдХреНрд╖рд░ (рдХреЗрд╕-рдЕрд╕рдВрд╡реЗрджреА рдЙрдк-рд╕реНрдЯреНрд░рд┐рдВрдЧ)ред
| `uninstallTimeoutMs` | `120000` | `dsh plugin remove` рдЪрд░рдг рдХреА рд╕рдордп-рд╕реАрдорд╛ред |
| `outputTailBytes` | `8000` | рдкреНрд░рддрд┐ рдЪрд░рдг рджрд░реНрдЬ рд╕реИрдирд┐рдЯрд╛рдЗрдЬрд╝реНрдб рдЖрдЙрдЯрдкреБрдЯ рдЯреЗрд▓ рдХреА рд╕реАрдорд╛ред |
| `keepTempDirs` | `false` | рд╡рд┐рдлрд▓рддрд╛ рдкрд░ рдлрд╝реЙрд░реЗрдВрд╕рд┐рдХ рд╣реЗрддреБ рдЕрд╕реНрдерд╛рдпреА рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛рдПрдБ рд░рдЦреЗрдВ (рд╕реНрд╡рд╛рдорд┐рддреНрд╡ рдЫреЛрдбрд╝рд╛ рдЬрд╛рддрд╛ рд╣реИ; рдЖрдк рд╕рд╛рдлрд╝ рдХрд░реЗрдВ)ред |
| `maxBatchTargets` | `20` | `/testdrive` рдмреИрдЪ рд╕реАрдорд╛ред |
| `batchConcurrency` | `1` | рдмреИрдЪ рд╕рдорд╛рдирд╛рдВрддрд░рддрд╛ (рдХреНрд░рдорд┐рдХ pnpm-рд╕реНрдЯреЛрд░ рд╡рд┐рд╡рд╛рдж рд╕реЗ рдмрдЪрд╛рддрд╛ рд╣реИ)ред |
## Tools & surfaces (рдЙрдкрдХрд░рдг рдФрд░ рд╕рддрд╣реЗрдВ)
### `test_drive`
```
test_drive(target: string, headlessTask?: string, background?: boolean,
capability?: { kind: 'tool' | 'command', name: string,
args: string, expect: string })
```
- `target` тАФ git рд╕реНрдкреЗрдХ (`github:owner/repo#sha`, `git+https://...`), npm рдирд╛рдо, рд╕реНрдерд╛рдиреАрдп рдкрде рдпрд╛ `.tgz` рдЯрд╛рд░рдмреЙрд▓ред
- `capability` тАФ рд╕реНрдореЛрдХ рдХреЗ рдмрд╛рдж рдХреА рдкреБрд╖реНрдЯрд┐: рдПрдЬреЗрдВрдЯ `args` рдХреЗ рд╕рд╛рде `name` (рдЙрдкрдХрд░рдг) рдмреБрд▓рд╛рддрд╛ рд╣реИ рдпрд╛ `/name` (рдХрдорд╛рдВрдб) рдЪрд▓рд╛рддрд╛ рд╣реИ; рдЪрд░рдг рдЯрд┐рдХрд╛рдК рд╕рддреНрд░ рд▓реЙрдЧ рдкрдврд╝рдХрд░ `expect` рд╡рд╛рд▓рд╛ рдкреНрд░реЗрдХреНрд╖рд┐рдд рдЖрдЙрдЯрдкреБрдЯ рдорд╛рдБрдЧрддрд╛ рд╣реИред `DEEPSEEK_API_KEY` рдЪрд╛рд╣рд┐рдП (рд╣реЛрд╕реНрдЯ рдкрд░рд┐рд╡реЗрд╢ рдпрд╛ `forwardEnv`); рдмрд┐рдирд╛ рдЙрд╕рдХреЗ рдЪрд░рдг `skipped` рд░рд╣рддрд╛ рд╣реИ, рдХрднреА рд╡рд┐рдлрд▓ рдирд╣реАрдВ рд╣реЛрддрд╛ред
- рдкреВрд░рд╛ рд╕рдВрд░рдЪрд┐рдд рд░рд┐рдХреЙрд░реНрдб рд▓реМрдЯрд╛рддрд╛ рд╣реИ; рдирдореВрдирд╛ рдиреАрдЪреЗред
- `background: true` рдПрдХ `drive-batch` рдХрд╛рд░реНрдп рдЖрд░рдВрдн рдХрд░ рдЙрд╕рдХрд╛ id рд▓реМрдЯрд╛рддрд╛ рд╣реИред
### `/testdrive <рд▓рдХреНрд╖реНрдп...>`
рдПрдХ рдкреГрд╖реНрдарднреВрдорд┐ рдмреИрдЪ рдХрд╛рд░реНрдп рдЖрд░рдВрдн рдХрд░рддрд╛ рд╣реИ; рдкреНрд░рдЧрддрд┐ рдХрд╛рд░реНрдп рдЖрдЙрдЯрдкреБрдЯ рд╕реЗ рдкреНрд░рд╡рд╛рд╣рд┐рдд рд╣реЛрддреА рд╣реИ, рдФрд░ рдЕрдВрддрд┐рдо рдкрдВрдХреНрддрд┐ `drive_report` рдХреЗ рд▓рд┐рдП рдореИрдЯреНрд░рд┐рдХреНрд╕ id рдмрддрд╛рддреА рд╣реИред
### `drive_report(id?)`
рдПрдХ рд░рди рд░рд┐рдХреЙрд░реНрдб (`tdr_...`), рдореИрдЯреНрд░рд┐рдХреНрд╕ (`tdm_...`), рдпрд╛ тАФ рдмрд┐рдирд╛ id тАФ рдирд╡реАрдирддрдо рдореИрдЯреНрд░рд┐рдХреНрд╕ рд▓реМрдЯрд╛рддрд╛ рд╣реИред
### рд╕рдВрд░рдЪрд┐рдд рдкрд░рд┐рдгрд╛рдо рдирдореВрдирд╛
```json
{
"schema": "dsh-test-drive/v1",
"run": { "runId": "tdr_9f2c...", "startedAt": "2026-08-16T00:00:00.000Z",
"finishedAt": "2026-08-16T00:00:45.120Z", "durationMs": 45120,
"harnessVersion": "0.1.7-rc.2", "pluginVersion": "0.3.10",
"platform": "win32", "node": "v22.22.3" },
"target": { "kind": "repo", "spec": "github:owner/dsh-click#abc123",
"resolved": { "packageName": "dsh-click", "packageVersion": "0.1.0",
"hasBundleManifest": true } },
"isolation": { "tempDshHome": true, "tempWorkspace": true, "tempStore": true,
"hostHomeTouched": false },
"stages": {
"install": { "status": "pass", "exitCode": 0, "durationMs": 30412, "attempts": 2,
"summary": "install ok after allowBuilds allowance", "outputTail": "",
"allowBuildsNeeded": true },
"config": { "status": "pass", "exitCode": 0, "durationMs": 2310, "attempts": 1,
"summary": "dump ok (exit 0)", "outputTail": "",
"patchEffective": true, "layers": ["dsh-click"] },
"smoke": { "status": "boot-ok", "exitCode": 1, "durationMs": 4123, "attempts": 1,
"summary": "booted without loader failures; headless task did not complete (credentials/model unreachable)",
"outputTail": "", "bootFailed": false, "taskCompleted": false },
"capability": { "status": "observed", "exitCode": 0, "durationMs": 8123, "attempts": 1,
"summary": "tool \"plugin_vet\" called and its result contains the expectation",
"outputTail": "", "capabilityKind": "tool", "name": "plugin_vet",
"expectMatched": true,
"detail": "tool \"plugin_vet\" called and its result contains the expectation" },
"uninstall": { "status": "pass", "exitCode": 0, "durationMs": 5123, "attempts": 1,
"summary": "remove ok (exit 0)", "outputTail": "" },
"cleanup": { "status": "pass", "quarantined": true, "removed": true,
"summary": "owned temp root quarantined and removed" }
},
"verdict": "pass",
"verdictReason": "install, patch, boot, and uninstall verified; headless task inconclusive (see smoke.summary)"
}
```
рдирд┐рд░реНрдгрдп рдирд┐рдпрдо: рдЗрдВрд╕реНрдЯреЙрд▓ рд╡рд┐рдлрд▓рддрд╛, рдмреВрдЯ рд╡рд┐рдлрд▓рддрд╛ (`smoke.fail`) рдпрд╛ `not-registered`/`failed` рддрдХ рдкрд╣реБрдБрдЪрд╛ рдХреНрд╖рдорддрд╛ рдЪрд░рдг тЗТ `fail`; рдЗрдВрд╕реНрдЯреЙрд▓ рдкрд╛рд╕ + рдкреИрдЪ рдкреНрд░рднрд╛рд╡реА + рд╕рд╛рдлрд╝ рдмреВрдЯ (`pass`/`boot-ok`) + рдЕрдирдЗрдВрд╕реНрдЯреЙрд▓ рдкрд╛рд╕ тЗТ `pass` (`observed` рдкрд░ рдХреНрд╖рдорддрд╛ рдиреЛрдЯ рдХреЗ рд╕рд╛рде); рдЗрдВрд╕реНрдЯреЙрд▓ рд╣реБрдЖ рдкрд░ рдмрд╛рдж рдХреА рдХреЛрдИ рдкреБрд╖реНрдЯрд┐ рдЕрдзреВрд░реА тЗТ `partial`; рдЕрдиреНрдпрдерд╛ тЗТ `unknown`ред
## CI (GitHub Actions)
рд░рд┐рдкреЙрдЬрд╝рд┐рдЯрд░реА рдореЗрдВ рдПрдХ composite [`action.yml`](action.yml) рд╢рд╛рдорд┐рд▓ рд╣реИ рдЬрд┐рд╕реЗ рдХрд┐рд╕реА рднреА рдкреНрд▓рдЧрдЗрди рд░рд┐рдкреЙ рдореЗрдВ `uses:` рд╕реЗ рджреЛрдмрд╛рд░рд╛ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ: рдпрд╣ рд▓рдХреНрд╖реНрдп рдХреЛ рдПрдХ рдЕрд▓рдЧ-рдерд▓рдЧ throwaway profile рдореЗрдВ рдЪрд▓рд╛рддрд╛ рд╣реИ рдФрд░ CI рджреНрд╡рд╛рд░рд╛ рдЙрдкрднреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рдиреЗ рд╡рд╛рд▓рд╛ рд░рд┐рдкреЛрд░реНрдЯ рдЬреЛрдбрд╝рд╛ тАФ Markdown (PR рдХрдореЗрдВрдЯ) рдФрд░ JUnit XML (рд╕реНрдЯреЗрдЯрд╕ рдЪреЗрдХ) тАФ рдЙрддреНрд╕рд░реНрдЬрд┐рдд рдХрд░рддрд╛ рд╣реИред рдЗрдирдкреБрдЯ `target` (рдЖрд╡рд╢реНрдпрдХ)/`headless-task`/`dsh-version`; рдЖрдЙрдЯрдкреБрдЯ `markdown`/`junit`/`verdict`ред рдбреНрд░рд╛рдЗрд╡ рдХреЛ рдХреБрдВрдЬреА рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ; рдХреЗрд╡рд▓ capability assertion рдХреЛ `DEEPSEEK_API_KEY` рдЪрд╛рд╣рд┐рдП рдФрд░ рдЗрд╕рдХреЗ рдмрд┐рдирд╛ рд╡рд╣ `skipped` (рдХрднреА рдЕрд╕рдлрд▓ рдирд╣реАрдВ) рд░рд╣рддреА рд╣реИред
## Permissions & data (рдЕрдиреБрдорддрд┐рдпрд╛рдБ рдФрд░ рдбреЗрдЯрд╛)
- рдХреЗрд╡рд▓ рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рд╕реЗрд╡рд╛рдПрдБ рдЙрдкрднреЛрдЧ рд╣реЛрддреА рд╣реИрдВ: `ctx.subprocess`, `ctx.jobs`, `ctx.storageDomain`, `ctx.tools`, `ctx.commands`ред
- рд░рд┐рдкреЛрд░реНрдЯреЗрдВ `test_drive` рд╕реНрдЯреЛрд░реЗрдЬ-рдбреЛрдореЗрди (рддрд╛рд▓рд┐рдХрд╛рдПрдБ `runs`, `matrices`; рдирд╡реАрдирддрдо-рдореИрдЯреНрд░рд┐рдХреНрд╕ рд╕рдВрдХреЗрддрдХ) рдореЗрдВ рд░рд╣рддреА рд╣реИрдВред рдЬрдм рд╕рдВрд░рдЪрдирд╛ рдореЗрдВ `storageDomain` рдирд╣реАрдВ рд╣реИ (рдЬреИрд╕реЗ рдЖрдзрд┐рдХрд╛рд░рд┐рдХ рд╣реЗрдбрд▓реЗрд╕ рдкреНрд░реЛрдлрд╝рд╛рдЗрд▓), рдЙрдкрдХрд░рдг рдЪрд▓рддреЗ рд░рд╣рддреЗ рд╣реИрдВ рдФрд░ рд░рд┐рдкреЛрд░реНрдЯ рд╕реНрдерд╛рдпрд┐рддреНрд╡ рдХрд╛рд░рдг рд╕рд╣рд┐рдд рдЕрдХреНрд╖рдо рд╣реЛрддрд╛ рд╣реИред
- рдЙрдк-рдкреНрд░рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреЛ **рдХреНрд░реЗрдбреЗрдВрд╢рд┐рдпрд▓-рд░рд╣рд┐рдд** рд╡рд╛рддрд╛рд╡рд░рдг рдорд┐рд▓рддрд╛ рд╣реИ: рд╣реЛрд╕реНрдЯ рд░рд╣рд╕реНрдп рддрдм рддрдХ рдкрд░реАрдХреНрд╖рд┐рдд рдкреНрд░реЛрдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдирд╣реАрдВ рдкрд╣реБрдБрдЪрддреЗ рдЬрдм рддрдХ рдЖрдк рдЙрдиреНрд╣реЗрдВ `forwardEnv` рдореЗрдВ рдирд╛рдо рди рджреЗрдВред рдорд╛рди рдХрднреА рд▓реЙрдЧ рдирд╣реАрдВ рд╣реЛрддреЗред
- рд╕рднреА рд░рд┐рдкреЛрд░реНрдЯ/рд▓реЙрдЧ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╢реБрджреНрдз рд╕реИрдирд┐рдЯрд╛рдЗрдЬрд╝рд░ рд╕реЗ рдЧреБрдЬрд╝рд░рддреА рд╣реИрдВ: рдЯреЛрдХрди рдЕрдХреНрд╖рд░, URL рдХреНрд░реЗрдбреЗрдВрд╢рд┐рдпрд▓ рдФрд░ bearer рд╣реЗрдбрд░ рд░рд┐рдбреИрдХреНрдЯ рд╣реЛрддреЗ рд╣реИрдВ, рдЕрд╕реНрдерд╛рдпреА рд░реВрдЯ рдкрде `` рд╕реЗ рдмрджрд▓реЗ рдЬрд╛рддреЗ рд╣реИрдВ, рдЯреЗрд▓ рдмрд╛рдЗрдЯ-рд╕реАрдорд┐рдд рд╣реЛрддреА рд╣реИрдВред
## Security boundaries (рд╕реБрд░рдХреНрд╖рд╛ рд╕реАрдорд╛рдПрдБ)
- **рдкреГрдердХреНрдХрд░рдгред** рд╣рд░ рдкрд░реАрдХреНрд╖рдг OS рдЕрд╕реНрдерд╛рдпреА рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдХреЗ рдЕрдВрджрд░ рдирдИ `mkdtemp` рд░реВрдЯ рдореЗрдВ рдЪрд▓рддрд╛ рд╣реИ: рдбрд┐рд╕реНрдкреЛрдЬрд╝реЗрдмрд▓ `DSH_HOME`, рдбрд┐рд╕реНрдкреЛрдЬрд╝реЗрдмрд▓ рдХрд╛рд░реНрдп рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛, рдФрд░ рдкреБрдирд░реНрдирд┐рд░реНрджреЗрд╢рд┐рдд pnpm рд╕реНрдЯреЛрд░ред рдкрд░реАрдХреНрд╖рд┐рдд рдкреНрд▓рдЧрдЗрди рдХрд╛ рдХреЛрдб рдХреЗрд╡рд▓ рдЙрд╕реА рдкреНрд░реЛрдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдЪрд▓рддрд╛ рд╣реИ; рдЖрдкрдХреА рд╣реЛрд╕реНрдЯ рдкреНрд░реЛрдлрд╝рд╛рдЗрд▓ рдЕрдЫреВрддреА рд░рд╣рддреА рд╣реИред
- **рд╕реНрд╡рд╛рдорд┐рддреНрд╡ред** рдПрдХ рд╕рдХреНрд░рд┐рдп рд░рдЬрд┐рд╕реНрдЯреНрд░реА рдЗрд╕ рдЗрдВрд╕реНрдЯреЗрдВрд╕ рдХреА рдмрдирд╛рдИ рд╣рд░ рд░реВрдЯ рдХреЛ рджрд░реНрдЬ рдХрд░рддреА рд╣реИред рд╕рдлрд╝рд╛рдИ рдХрд┐рд╕реА рднреА рдРрд╕реЗ рдкрде рдХреЛ рдЕрд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддреА рд╣реИ рдЬреЛ `dsh-test-drive-` рдЙрдкрд╕рд░реНрдЧ рдХреЗ рд╕рд╛рде OS рдЕрд╕реНрдерд╛рдпреА рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдХрд╛ рдкрдВрдЬреАрдХреГрдд рдкреНрд░рддреНрдпрдХреНрд╖ рдЙрдк-рдирд┐рд░реНрджреЗрд╢ рди рд╣реЛ тАФ рдХреЛрдИ `%TEMP%` рд╕рдлрд╝рд╛рдИ рдирд╣реАрдВ, рдХреЛрдИ рдкрд░рд╛рдпрд╛ рдЙрдкрд╕рд░реНрдЧ рдирд╣реАрдВ, рдХреЛрдИ рдЕрд╕рд▓реА рд╣реЛрдо рдкрде рдирд╣реАрдВред
- **рд╕рдлрд╝рд╛рдИ рдХреА рд╕реАрдврд╝реАред** рдХрд┐рд╕реА рднреА рдкрд░рд┐рд╡рд░реНрддрди рд╕реЗ рдкрд╣рд▓реЗ рдкреВрд░реА dry-run рдпреЛрдЬрдирд╛ рд▓реЙрдЧ рд╣реЛрддреА рд╣реИ (рдирд┐рд░рдкреЗрдХреНрд╖ рдкрде)ред рд╣рдЯрд╛рдирд╛ рдкрд╣рд▓реЗ рд░реВрдЯ рдХреЛ `dsh-test-drive-quarantine-` рдирд╛рдо рд╕реЗ рдХреНрд╡рд╛рд░рдВрдЯреАрди рдХрд░рддрд╛ рд╣реИ, рд╕рддреНрдпрд╛рдкрди рдХрд░рддрд╛ рд╣реИ, рдлрд┐рд░ рд╣рдЯрд╛рддрд╛ рд╣реИ; рд╡рд┐рдлрд▓рддрд╛ рдкрд░ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдХреНрд╡рд╛рд░рдВрдЯреАрди рд░рд╣рддреА рд╣реИ рдФрд░ рд╕реВрдЪрд┐рдд рд╣реЛрддреА рд╣реИ тАФ рдХрднреА рдЪреБрдкрдЪрд╛рдк рдирд╣реАрдВ рдЫреЛрдбрд╝реА рдЬрд╛рддреАред рд╕рдлрд╝рд╛рдИ рд╕рдлрд▓рддрд╛, рд╡рд┐рдлрд▓рддрд╛, рд╕рдордп-рд╕рдорд╛рдкреНрддрд┐ рдФрд░ рд░рджреНрджреАрдХрд░рдг рдХреЗ рд╣рд░ рд░рд╛рд╕реНрддреЗ рдореЗрдВ `finally` рдореЗрдВ рдЪрд▓рддреА рд╣реИ, рдФрд░ рдкреНрд▓рдЧрдЗрди рд╣рдЯрдиреЗ рдкрд░ рдлрд┐рд░ рдЪрд▓рддреА рд╣реИред
- **`allowBuilds` рдПрдХ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдЕрдиреБрдорддрд┐ рд╣реИред** git рдкреИрдХреЗрдЬ рдХреА `prepare` рдмрд┐рд▓реНрдб рдХреА рдЕрдиреБрдорддрд┐ рдЗрдВрд╕реНрдЯреЙрд▓ рдХреЗ рд╕рдордп рдЙрд╕ рдкреИрдХреЗрдЬ рдХрд╛ рдХреЛрдб рдЪрд▓рд╛рдирд╛ рд╣реИред рдЕрдиреБрдорддрд┐ рдХреЗрд╡рд▓ рдбрд┐рд╕реНрдкреЛрдЬрд╝реЗрдмрд▓ рдкреНрд░реЛрдлрд╝рд╛рдЗрд▓ рддрдХ рд╕реАрдорд┐рдд рд╣реИ, рдлрд┐рд░ рднреА рдХреЗрд╡рд▓ рднрд░реЛрд╕реЗрдордВрдж рд▓рдХреНрд╖реНрдпреЛрдВ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░реЗрдВ рдФрд░ commit рдкрд┐рди рдХрд░реЗрдВред
- **рд╣реЗрдбрд▓реЗрд╕ рд╕реНрдореЛрдХ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ рдХреБрдВрдЬреА-рд░рд╣рд┐рдд рд╣реИред** рдмреВрдЯ рдЬрд╛рдБрдЪ рдХреЛ рдХреНрд░реЗрдбреЗрдВрд╢рд┐рдпрд▓ рдирд╣реАрдВ рдЪрд╛рд╣рд┐рдП; рдПрдХ-рд╡рд╛рдХреНрдп рдХрд╛рд░реНрдп рдкреВрд░рд╛ рдХрд░рдиреЗ рдХреЛ рдЪрд╛рд╣рд┐рдПред рдХреНрд░реЗрдбреЗрдВрд╢рд┐рдпрд▓ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рднреЗрдЬреЗрдВ (`forwardEnv`) рдФрд░ рдЙрдиреНрд╣реЗрдВ рдХрднреА рд▓реЙрдЧ рди рдХрд░реЗрдВред
## Known limitations (рдЬреНрдЮрд╛рдд рд╕реАрдорд╛рдПрдБ)
- рд░рдЬрд┐рд╕реНрдЯреНрд░реА/git рд▓рдХреНрд╖реНрдп рдЗрдВрд╕реНрдЯреЙрд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдк-рдкреНрд░рдХреНрд░рд┐рдпрд╛ `dsh`/pnpm рдХреЛ рдиреЗрдЯрд╡рд░реНрдХ рдЪрд╛рд╣рд┐рдПред
- рд╕реНрдореЛрдХ рдХрд╛рд░реНрдп рдХреЛ `pass` рддрдХ рдкрд╣реБрдБрдЪрдиреЗ рдХреЗ рд▓рд┐рдП рдореЙрдбрд▓ рдХреНрд░реЗрдбреЗрдВрд╢рд┐рдпрд▓ рдЪрд╛рд╣рд┐рдП; рдмрд┐рдирд╛ рдЙрдирдХреЗ рдпрд╣ рдИрдорд╛рдирджрд╛рд░ `boot-ok` рджрд░реНрдЬ рдХрд░рддрд╛ рд╣реИред
- `storageDomain` рд░рд╣рд┐рдд рд╕рдВрд░рдЪрдирд╛рдУрдВ рдореЗрдВ рд░рд┐рдкреЛрд░реНрдЯреЗрдВ рд╕реНрдерд╛рдпреА рдирд╣реАрдВ рд╣реЛрддреАрдВ (`drive_report` рдИрдорд╛рдирджрд╛рд░реА рд╕реЗ рд╡рд┐рдлрд▓ рд╣реЛрддрд╛ рд╣реИ)ред
- `dsh` PATH рдкрд░ рдорд┐рд▓рдирд╛ рдЪрд╛рд╣рд┐рдП (рдпрд╛ `dshBin` рд╕реЗрдЯ рдХрд░реЗрдВ); Windows рдкрд░ npm рдХрд╛ `.cmd`/`.bat` shim рд╕реНрд╡рддрдГ рдкрд╛рд░реНрд╕ рд╣реЛрддрд╛ рд╣реИ, рдХреЗрд╡рд▓ `.ps1` рдорд┐рд▓рдиреЗ рдкрд░ `dshBin` рдорд╛рдБрдЧрд╛ рдЬрд╛рддрд╛ рд╣реИред
- рдмреИрдЪ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ рдХреНрд░рдорд┐рдХ рдЪрд▓рддреЗ рд╣реИрдВ; `batchConcurrency` рдмрдврд╝рд╛рдиреЗ рд╕реЗ рдХреЗрд╡рд▓ pnpm-рд╕реНрдЯреЛрд░ рдбрд┐рд╕реНрдХ рд╡рд┐рд╡рд╛рдж рдкреНрд░рднрд╛рд╡рд┐рдд рд╣реЛрддрд╛ рд╣реИ, рд╢реБрджреНрдзрддрд╛ рдирд╣реАрдВред
## Development (рд╡рд┐рдХрд╛рд╕)
```sh
pnpm install
pnpm run typecheck && pnpm run typecheck:ci && pnpm test
pnpm run build && pnpm run verify:self-contained && pnpm run verify:artifacts && pnpm pack
```
- `typecheck` рд╕реНрдерд╛рдиреАрдп harness рдЪреЗрдХрдЖрдЙрдЯ рд╕реЗ `@deepseek-ai/*` рд╣рд▓ рдХрд░рддрд╛ рд╣реИ; `typecheck:ci` рдкреНрд░рдХрд╛рд╢рд┐рдд `0.1.7-rc.2` рдкреНрд░рдХрд╛рд░реЛрдВ рд╕реЗ рдЬрд╛рдБрдЪрддрд╛ рд╣реИред
- рдкрд░реАрдХреНрд╖рдг рд╡рд╛рд╕реНрддрд╡рд┐рдХ `Context`/`Session`/`ToolRuntime`/`LocalJobRegistry`/рд╕реНрдЯреЛрд░реЗрдЬ рд╕реНрдЯреИрдХ рдФрд░ рдПрдХ рд╕реНрдХреНрд░рд┐рдкреНрдЯреЗрдб subprocess рдкреНрд░рджрд╛рддрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред
- рд╡рд╛рд╕реНрддрд╡рд┐рдХ-CLI рдПрдВрдб-рдЯреВ-рдПрдВрдб (рдиреЗрдЯрд╡рд░реНрдХ + PATH рдкрд░ `dsh` рдЖрд╡рд╢реНрдпрдХ): `DSH_TESTDRIVE_E2E=1 pnpm run test:e2e` тАФ рдЗрд╕реА рдкреИрдХреЗрдЬ рдХреЗ рдЪреЗрдХрдЖрдЙрдЯ рдХреЛ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдЗрдВрд╕реНрдЯреЙрд▓-рд╕реНрдореЛрдХ рд▓реВрдк рд╕реЗ рдкрд░рдЦрддрд╛ рд╣реИред
- рд░рд┐рд▓реАрдЬрд╝: `node scripts/release.mjs ` (рд╕рдВрд╕реНрдХрд░рдг рдмрдврд╝рд╛рддрд╛, CHANGELOG рдореБрд╣рд░ рд▓рдЧрд╛рддрд╛, рджреНрд╡рд╛рд░ рдлрд┐рд░ рдЪрд▓рд╛рддрд╛, commit + tag; рдХрднреА push рдирд╣реАрдВ)ред
## Topics
`dsh`, `dsh-plugin`, `deepseek-harness`, `deepseek`, `cordis`, `plugin-testing`, `install-smoke`, `compatibility-matrix`, `ci`
## Contributors (рдпреЛрдЧрджрд╛рдирдХрд░реНрддрд╛)
[PerryLink](https://github.com/PerryLink) тАФ рдбрд┐рдЬрд╝рд╛рдЗрди рдФрд░ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрдиред
## PerryLink DSH Plugin Family
рдпрд╣ рдкреНрд░реЛрдЬреЗрдХреНрдЯ [PerryLink](https://github.com/PerryLink) рдХреЗ DeepSeek Harness рдкреНрд▓рдЧрдЗрди рдкрд░рд┐рд╡рд╛рд░ рдХрд╛ рд╣рд┐рд╕реНрд╕рд╛ рд╣реИред рдкреВрд░реА рд╕реВрдЪреА рдиреАрдЪреЗ рд╕рдВрдХреНрд╖рд┐рдкреНрдд рд░рдЦреА рдЧрдИ рд╣реИ рддрд╛рдХрд┐ рд╣рд░ README рдХреА рдкрд╣рд▓реА рд╕реНрдХреНрд░реАрди рдЫреЛрдЯреА рд░рд╣реЗ; рд╣рд░ рдкрдВрдХреНрддрд┐ рдФрд░ рдЙрд╕рдХреА рд╕реНрдерд┐рддрд┐ рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдЗрд╕реЗ рдЦреЛрд▓реЗрдВред
рд╕рднреА рдкреНрд▓рдЧрдЗрди рдЦреЛрд▓реЗрдВ
| рдкреНрд▓рдЧрдЗрди | рд╕реНрдерд┐рддрд┐ |
|---|---|
| **[dsh-aqua-input-check](https://github.com/PerryLink/dsh-aqua-input-check)** | |
| **[dsh-archive-check](https://github.com/PerryLink/dsh-archive-check)** | |
| **[dsh-auto-review](https://github.com/PerryLink/dsh-auto-review)** | |
| **[dsh-autotier](https://github.com/PerryLink/dsh-autotier)** | |
| **[dsh-bid-ca-precheck](https://github.com/PerryLink/dsh-bid-ca-precheck)** | |
| **[dsh-bid-qual-check](https://github.com/PerryLink/dsh-bid-qual-check)** | |
| **[dsh-cert-mcp](https://github.com/PerryLink/dsh-cert-mcp)** | |
| **[dsh-checkpoint-rewind](https://github.com/PerryLink/dsh-checkpoint-rewind)** | |
| **[dsh-click](https://github.com/PerryLink/dsh-click)** | |
| **[dsh-composer-history](https://github.com/PerryLink/dsh-composer-history)** | |
| **[dsh-contract-stance](https://github.com/PerryLink/dsh-contract-stance)** | |
| **[dsh-customs-doc-check](https://github.com/PerryLink/dsh-customs-doc-check)** | |
| **[dsh-data-quality](https://github.com/PerryLink/dsh-data-quality)** | |
| **[dsh-demurrage-ledger](https://github.com/PerryLink/dsh-demurrage-ledger)** | |
| **[dsh-doublecheck](https://github.com/PerryLink/dsh-doublecheck)** | |
| **[dsh-drill-script-check](https://github.com/PerryLink/dsh-drill-script-check)** | |
| **[dsh-eia-guide-check](https://github.com/PerryLink/dsh-eia-guide-check)** | |
| **[dsh-emergency-plan](https://github.com/PerryLink/dsh-emergency-plan)** | |
| **[dsh-essay-rubric-check](https://github.com/PerryLink/dsh-essay-rubric-check)** | |
| **[dsh-evidence-check](https://github.com/PerryLink/dsh-evidence-check)** | |
| **[dsh-export-ctl-check](https://github.com/PerryLink/dsh-export-ctl-check)** | |
| **[dsh-fast](https://github.com/PerryLink/dsh-fast)** | |
| **[dsh-fmea-table-check](https://github.com/PerryLink/dsh-fmea-table-check)** | |
| **[dsh-forecast-penalty](https://github.com/PerryLink/dsh-forecast-penalty)** | |
| **[dsh-fund-research](https://github.com/PerryLink/dsh-fund-research)** | |
| **[dsh-github](https://github.com/PerryLink/dsh-github)** | |
| **[dsh-gongwen-flow-check](https://github.com/PerryLink/dsh-gongwen-flow-check)** | |
| **[dsh-gongwen-word-check](https://github.com/PerryLink/dsh-gongwen-word-check)** | |
| **[dsh-guard-plan-qc](https://github.com/PerryLink/dsh-guard-plan-qc)** | |
| **[dsh-hazchem-check](https://github.com/PerryLink/dsh-hazchem-check)** | |
| **[dsh-hazplan-check](https://github.com/PerryLink/dsh-hazplan-check)** | |
| **[dsh-hidden-risk-map](https://github.com/PerryLink/dsh-hidden-risk-map)** | |
| **[dsh-hs-classify](https://github.com/PerryLink/dsh-hs-classify)** | |
| **[dsh-icd-rule-check](https://github.com/PerryLink/dsh-icd-rule-check)** | |
| **[dsh-industry-research](https://github.com/PerryLink/dsh-industry-research)** | |
| **[dsh-lawcite-adapter](https://github.com/PerryLink/dsh-lawcite-adapter)** | |
| **[dsh-laya](https://github.com/PerryLink/dsh-laya)** | |
| **[dsh-lc-doc-check](https://github.com/PerryLink/dsh-lc-doc-check)** | |
| **[dsh-learning-gap-check](https://github.com/PerryLink/dsh-learning-gap-check)** | |
| **[dsh-library](https://github.com/PerryLink/dsh-library)** | |
| **[dsh-local-ai](https://github.com/PerryLink/dsh-local-ai)** | |
| **[dsh-lsp-actions](https://github.com/PerryLink/dsh-lsp-actions)** | |
| **[dsh-mask](https://github.com/PerryLink/dsh-mask)** | |
| **[dsh-mcp-panel](https://github.com/PerryLink/dsh-mcp-panel)** | |
| **[dsh-medrec-qc](https://github.com/PerryLink/dsh-medrec-qc)** | |
| **[dsh-memento](https://github.com/PerryLink/dsh-memento)** | |
| **[dsh-nsfc-form-check](https://github.com/PerryLink/dsh-nsfc-form-check)** | |
| **[dsh-nurse-record-check](https://github.com/PerryLink/dsh-nurse-record-check)** | |
| **[dsh-observe](https://github.com/PerryLink/dsh-observe)** | |
| **[dsh-origin-rvc-check](https://github.com/PerryLink/dsh-origin-rvc-check)** | |
| **[dsh-ota-review-check](https://github.com/PerryLink/dsh-ota-review-check)** | |
| **[dsh-output-styles](https://github.com/PerryLink/dsh-output-styles)** | |
| **[dsh-paper-doc-adapter](https://github.com/PerryLink/dsh-paper-doc-adapter)** | |
| **[dsh-permission-rules](https://github.com/PerryLink/dsh-permission-rules)** | |
| **[dsh-permit-report-check](https://github.com/PerryLink/dsh-permit-report-check)** | |
| **[dsh-pipeline-check](https://github.com/PerryLink/dsh-pipeline-check)** | |
| **[dsh-pleading-draft](https://github.com/PerryLink/dsh-pleading-draft)** | |
| **[dsh-plugin-doctor](https://github.com/PerryLink/dsh-plugin-doctor)** | |
| **[dsh-plugin-guide](https://github.com/PerryLink/dsh-plugin-guide)** | |
| **[dsh-plugin-kit](https://github.com/PerryLink/dsh-plugin-kit)** | |
| **[dsh-plugin-upgrade](https://github.com/PerryLink/dsh-plugin-upgrade)** | |
| **[dsh-policy-brief-draft](https://github.com/PerryLink/dsh-policy-brief-draft)** | |
| **[dsh-power-loss-split](https://github.com/PerryLink/dsh-power-loss-split)** | |
| **[dsh-power-ticket-check](https://github.com/PerryLink/dsh-power-ticket-check)** | |
| **[dsh-ppap-check](https://github.com/PerryLink/dsh-ppap-check)** | |
| **[dsh-protest-deadline](https://github.com/PerryLink/dsh-protest-deadline)** | |
| **[dsh-railway-window](https://github.com/PerryLink/dsh-railway-window)** | |
| **[dsh-repair-order-qc](https://github.com/PerryLink/dsh-repair-order-qc)** | |
| **[dsh-research-report](https://github.com/PerryLink/dsh-research-report)** | |
| **[dsh-review-reply-check](https://github.com/PerryLink/dsh-review-reply-check)** | |
| **[dsh-rulefile-check](https://github.com/PerryLink/dsh-rulefile-check)** | |
| **[dsh-safety-brief-check](https://github.com/PerryLink/dsh-safety-brief-check)** | |
| **[dsh-score](https://github.com/PerryLink/dsh-score)** | |
| **[dsh-session-sync](https://github.com/PerryLink/dsh-session-sync)** | |
| **[dsh-site-log-check](https://github.com/PerryLink/dsh-site-log-check)** | |
| **[dsh-skill-pack-security](https://github.com/PerryLink/dsh-skill-pack-security)** | |
| **[dsh-soe-decision-check](https://github.com/PerryLink/dsh-soe-decision-check)** | |
| **[dsh-soilwater-check](https://github.com/PerryLink/dsh-soilwater-check)** | |
| **[dsh-sop-sync-check](https://github.com/PerryLink/dsh-sop-sync-check)** | |
| **[dsh-spc-gbt-adapter](https://github.com/PerryLink/dsh-spc-gbt-adapter)** | |
| **[dsh-talk](https://github.com/PerryLink/dsh-talk)** | |
| **[dsh-tender-extract](https://github.com/PerryLink/dsh-tender-extract)** | |
| **[dsh-tender-matrix](https://github.com/PerryLink/dsh-tender-matrix)** | |
| **[dsh-test-drive](https://github.com/PerryLink/dsh-test-drive)** | |
| **[dsh-ticktick](https://github.com/PerryLink/dsh-ticktick)** | |
| **[dsh-translate](https://github.com/PerryLink/dsh-translate)** | |
| **[dsh-warranty-calc](https://github.com/PerryLink/dsh-warranty-calc)** | |
| **[dsh-budget](https://github.com/PerryLink/dsh-budget)** | ЁЯзК рдлрд╝реНрд░реЛрдЬрд╝рди тАФ рд░рд┐рдкреЙрдЬрд╝рд┐рдЯрд░реА README рджреЗрдЦреЗрдВ |
| **[dsh-claude-move](https://github.com/PerryLink/dsh-claude-move)** | ЁЯзК рдлрд╝реНрд░реЛрдЬрд╝рди тАФ рд░рд┐рдкреЙрдЬрд╝рд┐рдЯрд░реА README рджреЗрдЦреЗрдВ |
| **[dsh-defend](https://github.com/PerryLink/dsh-defend)** | ЁЯзК рдлрд╝реНрд░реЛрдЬрд╝рди тАФ рд░рд┐рдкреЙрдЬрд╝рд┐рдЯрд░реА README рджреЗрдЦреЗрдВ |
| **[dsh-draw](https://github.com/PerryLink/dsh-draw)** | ЁЯзК рдлрд╝реНрд░реЛрдЬрд╝рди тАФ рд░рд┐рдкреЙрдЬрд╝рд┐рдЯрд░реА README рджреЗрдЦреЗрдВ |
| **[dsh-reach](https://github.com/PerryLink/dsh-reach)** | ЁЯзК рдлрд╝реНрд░реЛрдЬрд╝рди тАФ рд░рд┐рдкреЙрдЬрд╝рд┐рдЯрд░реА README рджреЗрдЦреЗрдВ |
| **[dsh-background-agents](https://github.com/PerryLink/dsh-background-agents)** | ЁЯЪл рд╕реЗрд╡рд╛рдирд┐рд╡реГрддреНрдд тАФ рд░рд┐рдкреЙрдЬрд╝рд┐рдЯрд░реА README рджреЗрдЦреЗрдВ |
| **[dsh-session-pin](https://github.com/PerryLink/dsh-session-pin)** | ЁЯЪл рд╕реЗрд╡рд╛рдирд┐рд╡реГрддреНрдд тАФ рд░рд┐рдкреЙрдЬрд╝рд┐рдЯрд░реА README рджреЗрдЦреЗрдВ |
| **[dsh-team-rooms](https://github.com/PerryLink/dsh-team-rooms)** | ЁЯЪл рд╕реЗрд╡рд╛рдирд┐рд╡реГрддреНрдд тАФ рд░рд┐рдкреЙрдЬрд╝рд┐рдЯрд░реА README рджреЗрдЦреЗрдВ |
## License (рд▓рд╛рдЗрд╕реЗрдВрд╕)
[Apache-2.0](LICENSE)
### DSH Desktop рдорд╛рд░реНрдХреЗрдЯ рд╕реЗ рдЗрдВрд╕реНрдЯреЙрд▓ рдХрд░реЗрдВ
рд╕рднреА PerryLink рдкреНрд▓рдЧрдЗрди DSH Desktop рдХреЗ рдмрд┐рд▓реНрдЯ-рдЗрди рдорд╛рд░реНрдХреЗрдЯ рдореЗрдВ рджреЗрдЦреЗ рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВ: **Market тЖТ Sources тЖТ add source тЖТ рдкреЗрд╕реНрдЯ рдХрд░реЗрдВ** `https://perrylink-dsh-catalog.perrylink.workers.dev/catalog-source.json` **тЖТ рдЪреБрдиреЗрдВ**ред рдЗрдВрд╕реНрдЯреЙрд▓реЗрд╢рди рдорд╛рд░реНрдХреЗрдЯ рдХреЗ npm-identity рд╕рддреНрдпрд╛рдкрди рдФрд░ рдЖрдкрдХреА рдкреБрд╖реНрдЯрд┐ рд╕реЗ рд╣реА рд╣реЛрддрд╛ рд╣реИред
### рдЙрджрд╛рд╣рд░рдг
рдпреЗ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдкреНрд░рд╡реЗрд╢ рдмрд┐рдВрджреБ рд╣реИрдВ; рдЗрдВрд╕реНрдЯреЙрд▓ рдХреЗ рдмрд╛рдж рдПрдХ рдЪрд▓рд╛рдПрдБред
#### рд╡рд┐рд╕реНрддреГрдд рдЙрджрд╛рд╣рд░рдг
**рдХрдорд╛рдВрдб**
~~~sh
test_drive({ target: "dsh-click" })
~~~
**рдЖрдЙрдЯрдкреБрдЯ**
~~~text
# Test drive tdr_0b9b6e6a61e3e80cc4620f2e
- Target: `dsh-click` (npm)
- Verdict: тЬЕ pass тАФ install, patch, boot, task, and uninstall all verified
- Installed: dsh-click@0.2.0
- Isolation: throwaway DSH_HOME + workspace + pnpm store; host profile untouched
| Stage | Result | Exit | Duration | Summary |
|---|---|---|---|---|
| install | тЬЕ pass | 0 | 1 ms | install ok (exit 0) |
| config (--dump-config) | тЬЕ pass | 0 | 0 ms | patch effective: dsh-click |
| smoke (headless boot) | тЬЕ pass | 0 | 0 ms | booted cleanly and the headless task completed |
| capability | тПня╕П skipped | null | 0 ms | capability assertion disabled (config.capability.enabled is false and no per-drive capability given) |
| uninstall | тЬЕ pass | 0 | 0 ms | remove ok (exit 0) |
| cleanup | тЬЕ pass | тАФ | тАФ | owned temp root quarantined and removed |
~~~
*рд╕реНрд░реЛрдд `README.md:153-163,174-211; tests/drive.spec.ts:73-101; src/report.ts:34-55`*
#### рд╡рд┐рдлрд▓рддрд╛ рд╢рд╛рдЦрд╛
**рдЗрдирдкреБрдЯ**
~~~text
{"target":" "}
~~~
**рдЖрдЙрдЯрдкреБрдЯ**
~~~text
isError=true; error.message=dsh-test-drive: target must be a non-empty string
~~~
*рд╕реНрд░реЛрдд `plugins/dsh-test-drive/src/tools.ts:297-299 (blank target check); exercised through plugins/dsh-test-drive/tests/harness.ts`*
#### рд╕рдВрдХреНрд╖рд┐рдкреНрдд рдЙрджрд╛рд╣рд░рдг