@perrylink/dsh-github 0.6.0 → 0.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.es.md +153 -194
- package/README.hi.md +153 -194
- package/README.md +122 -187
- package/README.pt.md +146 -187
- package/README.zh.md +230 -0
- package/cordis.patch.yml +1 -1
- package/package.json +121 -82
- package/scripts/action-patch.mjs +152 -138
- package/scripts/action-post.mjs +61 -48
- package/scripts/check-readmes.mjs +3 -1
- package/scripts/local-test.mjs +259 -0
- package/README.zh-CN.md +0 -292
package/README.md
CHANGED
|
@@ -1,131 +1,90 @@
|
|
|
1
|
-
<
|
|
2
|
-
|
|
3
|
-
<p align="center">
|
|
4
|
-
<b>Bring GitHub into DeepSeek Harness.</b><br/>
|
|
5
|
-
Create pull requests · review PRs with inline or summary comments · manage issues · search — every write gated by human approval, token never logged.
|
|
6
|
-
</p>
|
|
7
|
-
|
|
8
|
-
<p align="center">
|
|
9
|
-
<a href="README.zh-CN.md">中文</a> ·
|
|
10
|
-
<a href="README.es.md">Español</a> ·
|
|
11
|
-
<a href="README.pt.md">Português</a> ·
|
|
12
|
-
<a href="README.hi.md">हिन्दी</a>
|
|
13
|
-
</p>
|
|
14
|
-
|
|
15
|
-
<p align="center">
|
|
16
|
-
<img src="https://img.shields.io/badge/license-Apache%202.0-blue.svg" alt="License: Apache 2.0">
|
|
17
|
-
<img src="https://img.shields.io/badge/dsh-0.1.0--rc.6-4D6BFE" alt="dsh: 0.1.0-rc.6">
|
|
18
|
-
<img src="https://img.shields.io/badge/dsh-dsh--plugin-4D6BFE" alt="dsh-plugin">
|
|
19
|
-
<img src="https://img.shields.io/badge/node-%5E22.19%20%7C%7C%20%3E%3D24-brightgreen" alt="Node: ^22.19 || >=24">
|
|
20
|
-
<img src="https://github.com/PerryLink/dsh-github/actions/workflows/ci.yml/badge.svg" alt="CI">
|
|
21
|
-
<img src="https://img.shields.io/badge/documents-EN%2FZH%2FES%2FPT%2FHI-8257D0" alt="Documents: EN/ZH/ES/PT/HI">
|
|
22
|
-
</p>
|
|
1
|
+
<div align="center">
|
|
23
2
|
|
|
24
|
-
|
|
3
|
+
# dsh-github
|
|
4
|
+
|
|
5
|
+
**GitHub PRs, reviews, issues, and CI for DeepSeek Harness — every write gated by human approval, token never logged.**
|
|
6
|
+
|
|
7
|
+
*Create, review, merge, and search GitHub from the agent, with a CI composite action, polling review bot, and status-check gate.*
|
|
8
|
+
|
|
9
|
+
[](LICENSE)
|
|
10
|
+
[](https://github.com/topics/dsh-plugin)
|
|
11
|
+
[](#)
|
|
12
|
+
[](https://github.com/PerryLink/dsh-github/actions)
|
|
13
|
+
[](https://github.com/PerryLink/dsh-github/releases)
|
|
14
|
+
[](https://www.npmjs.com/package/@perrylink/dsh-github)
|
|
15
|
+
[](https://www.npmjs.com/package/@perrylink/dsh-github)
|
|
25
16
|
|
|
26
|
-
|
|
17
|
+
[English](README.md) · [简体中文](README.zh.md) · [Español](README.es.md) · [Português](README.pt.md) · [हिन्दी](README.hi.md)
|
|
27
18
|
|
|
28
|
-
|
|
29
|
-
- ⌨️ **3 command families** — `/pr create` · `/review` (start/stop/post) · `/issue open`
|
|
30
|
-
- 🔀 **Full PR lifecycle** — create → review → update (title/body/state/base) → merge (merge/squash/rebase, optional head-branch delete)
|
|
31
|
-
- 📝 **Inline reviews** — `review_post` posts either one summary comment or line-anchored review comments against the PR head commit
|
|
32
|
-
- 🔒 **Approval-gated writes** — every GitHub write goes through `ctx.approval` (default `ask`, fail-closed); approval reasons preview titles, body sizes, and comment overrides
|
|
33
|
-
- 🗝 **Token secrecy** — credentials seam → environment → `gh` CLI, resolved per operation, never in logs, events, renders, or errors
|
|
34
|
-
- 🖥 **Background review jobs** — `/review` runs on `ctx.jobs` with the host's own `job_list` / `job_output` / `job_kill` surface, and reports CI status and comment counts alongside the findings
|
|
35
|
-
- 🤖 **Model review option** — `reviewMode: "model"` delegates the capped diff to a one-shot subagent through the host's `subagents` seam; the default `static` mode stays deterministic and token-free
|
|
36
|
-
- 🚦 **429 backoff + quota surfacing** — the model sees the remaining rate limit on every result, including failures; per-section fetch errors are surfaced instead of swallowed
|
|
37
|
-
- 🌐 **5-language docs** — English · 中文 · Español · Português · हिन्दी
|
|
19
|
+
</div>
|
|
38
20
|
|
|
39
21
|
---
|
|
40
22
|
|
|
41
23
|
## 📚 Table of contents
|
|
42
24
|
|
|
43
|
-
- [
|
|
44
|
-
- [
|
|
45
|
-
- [
|
|
46
|
-
- [
|
|
47
|
-
- [
|
|
48
|
-
- [
|
|
49
|
-
- [Architecture](
|
|
50
|
-
- [
|
|
51
|
-
- [
|
|
52
|
-
- [
|
|
53
|
-
- [
|
|
54
|
-
- [
|
|
55
|
-
- [
|
|
25
|
+
- [Compatibility](#compatibility)
|
|
26
|
+
- [What you get](#what-you-get)
|
|
27
|
+
- [Quick start](#quick-start)
|
|
28
|
+
- [Install & uninstall](#install-&-uninstall)
|
|
29
|
+
- [Configuration](#configuration)
|
|
30
|
+
- [Tools & surfaces](#tools-&-surfaces)
|
|
31
|
+
- [Architecture](#architecture)
|
|
32
|
+
- [Permissions & data](#permissions-&-data)
|
|
33
|
+
- [Security boundaries](#security-boundaries)
|
|
34
|
+
- [Known limitations](#known-limitations)
|
|
35
|
+
- [Development](#development)
|
|
36
|
+
- [Repository layout](#repository-layout)
|
|
37
|
+
- [Topics](#topics)
|
|
38
|
+
- [Contributors](#contributors)
|
|
56
39
|
- [PerryLink DSH Plugin Family](#perrylink-dsh-plugin-family)
|
|
40
|
+
- [License](#license)
|
|
57
41
|
|
|
58
|
-
##
|
|
42
|
+
## Compatibility
|
|
59
43
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
# 2. configure a GitHub token (recommended: the credentials seam)
|
|
68
|
-
# $DSH_HOME/.credentials.yaml
|
|
69
|
-
# GITHUB_TOKEN: <your token>
|
|
70
|
-
|
|
71
|
-
# 3. use it — in the dsh web UI or headless
|
|
72
|
-
# /pr create "add dark mode" → agent drafts & opens the PR (approval required)
|
|
73
|
-
# /review 42 → background review job, read it with job_output
|
|
74
|
-
# /review post github-review-1 → publish the review comment (approval required)
|
|
75
|
-
# /issue open "crash on startup" → agent opens the issue (approval required)
|
|
76
|
-
```
|
|
44
|
+
| Surface | Status |
|
|
45
|
+
|---|---|
|
|
46
|
+
| Harness | DeepSeek Harness `0.1.0-rc.6` (compat declared for `0.1.0-rc.5`–`0.1.0-rc.6`) |
|
|
47
|
+
| Node | `^22.19.0 \|\| >=24.0.0` |
|
|
48
|
+
| Platforms | All (host plugin; outbound network to GitHub) |
|
|
49
|
+
| Model | Any (static review is deterministic; `reviewMode: "model"` is optional) |
|
|
77
50
|
|
|
78
|
-
|
|
51
|
+
## What you get
|
|
79
52
|
|
|
80
|
-
|
|
53
|
+
`dsh-github` fills the GitHub gap between `dsh` and tools like Claude Code and Codex: your agent can read, review, open, update, and merge pull requests, read repository metadata and files, comment on and close issues, and search — while a human approves every write and the token stays secret.
|
|
81
54
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
| **Read files** | `gh_file` reads one file at a branch/tag/commit with base64 decoding and a configurable cap; directories report a structured error |
|
|
92
|
-
| **Read issues** | `gh_issue` lists / gets / comments; pull requests in listings are marked `kind: "pr"` |
|
|
93
|
-
| **Manage issues** | `issue_open` creates, `issue_comment` comments (also works on PRs), `issue_close` closes with an optional state reason — all approval-gated |
|
|
94
|
-
| **Search** | `gh_search` queries issues and pull requests with GitHub search syntax, surfacing the separate search quota |
|
|
95
|
-
| **Approval** | `tools/pre-execute` asks `ctx.approval` for every write; `allowedActions` whitelist denies before prompting |
|
|
96
|
-
| **Secret safety** | Token is read per operation and sent only in the Authorization header; a dedicated test asserts it never appears in any visible output |
|
|
97
|
-
| **Resilience** | 429 retry with `Retry-After`/`x-ratelimit-reset` backoff; read tools are concurrency-safe; all calls honor cancellation |
|
|
98
|
-
| **Observability** | Model-visible ⇔ logged: everything the model sees flows through the host's own session events (`tool/result`, `user/message`, `command/run`, `approval/asked`…) |
|
|
99
|
-
|
|
100
|
-
## 📦 Installation
|
|
101
|
-
|
|
102
|
-
Four documented channels — pick one.
|
|
103
|
-
|
|
104
|
-
| Channel | Command | Notes |
|
|
105
|
-
|---|---|---|
|
|
106
|
-
| **npm registry** | `dsh plugin --profile <name> add @perrylink/dsh-github` | Published package — the simplest channel |
|
|
107
|
-
| **npm tarball** | `dsh plugin --profile <name> add ./dsh-github-<version>.tgz` | Ships with `lib/` built — no build permission |
|
|
108
|
-
| **git source** | `dsh plugin --profile <name> add "github:PerryLink/dsh-github#<sha>"` | Needs `prepare` + `allowBuilds` (see below); pin the commit |
|
|
109
|
-
| **local link** | `pnpm link --dir .` then `dsh plugin add @perrylink/dsh-github` | Development |
|
|
55
|
+
- **12 tools** — `pr_create`, `pr_merge`, `pr_update`, `gh_review`, `review_post`, `gh_issue`, `issue_open`, `issue_comment`, `issue_close`, `gh_search`, `gh_repo`, `gh_file`, all canonical JSON via `defineTool`.
|
|
56
|
+
- **3 command families** — `/pr create`, `/review` (start/stop/post), `/issue open`.
|
|
57
|
+
- **Full PR lifecycle** — create → review → update (title/body/state/base) → merge (merge/squash/rebase, optional head-branch delete).
|
|
58
|
+
- **Inline reviews** — `review_post` posts one summary comment or line-anchored review comments against the PR head commit.
|
|
59
|
+
- **Approval-gated writes** — every GitHub write goes through `ctx.approval` (default `ask`, fail-closed); approval reasons preview titles, body sizes, and comment overrides.
|
|
60
|
+
- **Token secrecy** — credentials seam → environment → `gh` CLI, resolved per operation, never in logs, events, renders, or errors.
|
|
61
|
+
- **Background review jobs** — `/review` runs on `ctx.jobs` with the host's own `job_list` / `job_output` / `job_kill` surface.
|
|
62
|
+
- **Resilience** — 429 retry with `Retry-After`/`x-ratelimit-reset` backoff; read tools are concurrency-safe; all calls honor cancellation.
|
|
63
|
+
- **CI surface** — the one-shot `ci_run` tool, a polling review bot, and a status-check gate (composite action `action.yml`).
|
|
110
64
|
|
|
111
|
-
|
|
112
|
-
> unscoped `dsh-github` name is owned by an unrelated project on the registry.
|
|
113
|
-
> The plugin's module name stays `dsh-github`.
|
|
65
|
+
## Quick start
|
|
114
66
|
|
|
115
|
-
|
|
67
|
+
```sh
|
|
68
|
+
# 1. install the bundle into your profile
|
|
69
|
+
dsh plugin --profile web add "github:PerryLink/dsh-github#main"
|
|
70
|
+
|
|
71
|
+
# or from npm (published releases)
|
|
72
|
+
dsh plugin --profile web add @perrylink/dsh-github
|
|
116
73
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
'@perrylink/dsh-github': true
|
|
74
|
+
# 2. restart and verify the row
|
|
75
|
+
dsh --profile web --dump-config | grep -A3 'id: dsh-github'
|
|
120
76
|
```
|
|
121
77
|
|
|
122
|
-
|
|
78
|
+
## Install & uninstall
|
|
123
79
|
|
|
124
|
-
**
|
|
80
|
+
- **git channel** (latest `main`): `dsh plugin --profile web add "github:PerryLink/dsh-github#main"` — the `prepare` script builds with production dependencies only.
|
|
81
|
+
- **npm channel** (published releases): `dsh plugin --profile web add @perrylink/dsh-github`.
|
|
82
|
+
- **tarball channel**: `pnpm pack` in this repo, then `dsh plugin --profile web add ./dsh-github-<version>.tgz`.
|
|
83
|
+
- **uninstall**: `dsh plugin --profile web remove dsh-github` (or remove the row from the profile patch).
|
|
125
84
|
|
|
126
|
-
##
|
|
85
|
+
## Configuration
|
|
127
86
|
|
|
128
|
-
Schemastery
|
|
87
|
+
All tunables are Schemastery `Config` fields (changeable from cordis.yml). An id-targeted override replaces the whole row — restate every key you need. `cordis.patch.yml` documents each key inline.
|
|
129
88
|
|
|
130
89
|
| Key | Default | Meaning |
|
|
131
90
|
|---|---|---|
|
|
@@ -152,97 +111,71 @@ Schemastery-validated at load time (fail loud). Override any key in the profile'
|
|
|
152
111
|
| `workspaceDir` | process cwd | Working directory for read-only git inspection |
|
|
153
112
|
| `ci` | `{ enabled: false, … }` | CI integration section: polling review bot, status-check gate, and the one-shot `ci_run` tool (all `ci.*` keys live inside it) |
|
|
154
113
|
|
|
155
|
-
##
|
|
156
|
-
|
|
157
|
-
| Tool | Kind | Parameters | Returns |
|
|
158
|
-
|---|---|---|---|
|
|
159
|
-
| `pr_create` | write | `title*`, `body?`, `base?`, `head?`, `draft?`, `ownerRepo?` | `{status:'created', url, number, title, state, draft, base, head, rateLimit}` or structured error |
|
|
160
|
-
| `pr_merge` | write | `pr*` (number / `#n` / `o/r#n` / URL), `mergeMethod?`, `commitTitle?`, `commitMessage?`, `deleteBranch?` | `{status:'merged', merged, sha?, message, url, branchDeleted, branchDeleteNote?, rateLimit}` or structured error |
|
|
161
|
-
| `pr_update` | write | `pr*` (number / `#n` / `o/r#n` / URL), `title?`, `body?`, `state?` (`open`/`closed`), `base?` | `{status:'updated', url, number, title, state, base, rateLimit}` or structured error |
|
|
162
|
-
| `gh_review` | read | `pr*` (number / `#n` / `o/r#n` / URL), `fields?`, `maxDiffChars?` | metadata, capped diff (full `diff.text` + bounded `diff.excerpt` + per-file stats), comments, CI, static findings, per-section `error` fields, rate limit |
|
|
163
|
-
| `gh_repo` | read | `ownerRepo?` | `{repo, description, defaultBranch, visibility, stars, forks, openIssues, language, license, topics, url, updatedAt, rateLimit}` or structured error |
|
|
164
|
-
| `gh_file` | read | `ownerRepo?`, `path*`, `ref?`, `maxChars?` | `{repo, path, ref, size, truncated, content, sha, url, rateLimit}` or structured error |
|
|
165
|
-
| `gh_issue` | read | `action*` (`list`/`get`/`comments`), `ownerRepo?`, `issueNumber?`, `state?`, `limit?` | normalized items (each marked `kind: issue/pr/comment`) + rate limit |
|
|
166
|
-
| `review_post` | write | `jobId*`, `mode?` (`summary`/`inline`), `body?` | `{status:'posted', mode, url, commentId?, reviewId?, findings, rateLimit}` or structured error |
|
|
167
|
-
| `issue_open` | write | `title*`, `body?`, `labels?`, `ownerRepo?` | `{status:'created', url, number, title, rateLimit}` or structured error |
|
|
168
|
-
| `issue_comment` | write | `issueNumber*`, `body*`, `ownerRepo?` | `{status:'commented', url, commentId, issueNumber, rateLimit}` or structured error |
|
|
169
|
-
| `issue_close` | write | `issueNumber*`, `ownerRepo?`, `stateReason?` (`completed`/`not_planned`) | `{status:'closed', url, number, title, rateLimit}` or structured error |
|
|
170
|
-
| `gh_search` | read | `q*`, `sort?`, `order?`, `perPage?` | `{query, total, items[{number,title,state,kind,author,url,repo,comments,createdAt}], rateLimit}` or structured error |
|
|
114
|
+
## Tools & surfaces
|
|
171
115
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
|
177
|
-
|
|
178
|
-
|
|
|
179
|
-
|
|
|
180
|
-
|
|
|
181
|
-
|
|
|
182
|
-
|
|
|
183
|
-
|
|
|
116
|
+
| Surface | Kind | Notes |
|
|
117
|
+
|---|---|---|
|
|
118
|
+
| `pr_create` | tool | Create a pull request (write; approval-gated) |
|
|
119
|
+
| `pr_merge` | tool | Merge a PR (merge/squash/rebase, optional head-branch delete) |
|
|
120
|
+
| `pr_update` | tool | Update a PR (title/body/state/base) |
|
|
121
|
+
| `gh_review` | tool | Read a PR: metadata, capped diff, comments, CI, static findings |
|
|
122
|
+
| `review_post` | tool | Publish a review comment (summary or line-anchored inline) |
|
|
123
|
+
| `gh_issue` | tool | List / get / comment on issues (PRs marked `kind: "pr"`) |
|
|
124
|
+
| `issue_open` | tool | Create an issue |
|
|
125
|
+
| `issue_comment` | tool | Comment on an issue or PR |
|
|
126
|
+
| `issue_close` | tool | Close an issue (optional state reason) |
|
|
127
|
+
| `gh_search` | tool | Search issues and PRs (separate search quota) |
|
|
128
|
+
| `gh_repo` | tool | Read repository metadata |
|
|
129
|
+
| `gh_file` | tool | Read one file at a branch/tag/commit |
|
|
130
|
+
| `/pr create` | command | Read git state and queue a `pr_create` instruction |
|
|
131
|
+
| `/review` | command | Start / stop / post a background review job |
|
|
132
|
+
| `/issue open` | command | Queue an `issue_open` instruction |
|
|
133
|
+
| `ci_run` | tool | One-shot CI review run by the composite action / CI driver |
|
|
134
|
+
| review bot | surface | Polling review bot with idempotent inline comments (`ci.*`) |
|
|
135
|
+
| status-check gate | surface | Publishes the `success` / `needs-changes` verdict per PR head commit (`action.yml`) |
|
|
136
|
+
|
|
137
|
+
## Architecture
|
|
184
138
|
|
|
185
|
-
|
|
139
|
+
- **Credential seam.** `tokenSource: auto` resolves per operation in the order credentials seam (`GITHUB_TOKEN` reference) → environment variable → `gh` CLI token. The value is a local variable handed to the REST client; it never enters canonical values, renders, cards, command outputs, injected notices, job output, approval reasons, or error messages.
|
|
140
|
+
- **Approval gate.** All writes flow through model tools. A `tools/pre-execute` waterfall listener returns `ask` for the write tools, so the registry asks the human through `ctx.approval` (the host logs the `approval/asked` + `approval/decided` audit pair) and fails closed without an answerer. Commands never write directly: a write command gathers read-only context, then wakes the agent so the model runs the gated tool inside a turn.
|
|
141
|
+
- **Background review job.** `/review <pr>` starts a `github-review` job on `ctx.jobs`; the job fetches metadata (capturing the head-commit SHA for inline posting), the capped diff, CI checks, and existing comments, then runs the deterministic multi-file analyzer (`src/review.ts`). With `reviewMode: "model"`, the job hands the capped diff to a one-shot subagent through the host's `subagents` seam. Completion reaches the session through the host's `dsh-tool-jobs` consumer; the model reads it with `job_output` and publishes it with `review_post`.
|
|
142
|
+
- **CI composite action / review bot / status-check gate.** The repo ships a composite action (`action.yml`) that reviews PRs, fixes CI, and writes the report; a polling review bot posts idempotent inline comments; and a status-check gate publishes the verdict per PR head commit. The one-shot `ci_run` tool drives the headless run. Every write stays approval-gated.
|
|
186
143
|
|
|
187
|
-
|
|
188
|
-
┌───────────────────────────────────────────────┐
|
|
189
|
-
│ dsh-github │
|
|
190
|
-
│ │
|
|
191
|
-
humans ─── /pr ────┼──► git reader (read-only) ──► agent.followup │
|
|
192
|
-
/review ───┼──► ctx.jobs.start("github-review") ──► job │
|
|
193
|
-
/issue ────┼──► agent.followup │
|
|
194
|
-
│ │
|
|
195
|
-
model ─── pr_create / pr_merge / pr_update / gh_review / │
|
|
196
|
-
review_post / gh_issue / issue_open / issue_comment / │
|
|
197
|
-
issue_close / gh_search / gh_repo / gh_file │
|
|
198
|
-
(defineTool, canonical JSON only) │
|
|
199
|
-
│ │
|
|
200
|
-
└───────┬───────────────┬───────────────┬───────┘
|
|
201
|
-
│ │ │
|
|
202
|
-
tools/pre-execute credential GitHub REST
|
|
203
|
-
approval gate resolution client (fetch,
|
|
204
|
-
(ask | deny) (seam → env → 429 retry,
|
|
205
|
-
gh CLI, per-op) rate-limit)
|
|
206
|
-
```
|
|
144
|
+
## Permissions & data
|
|
207
145
|
|
|
208
|
-
- **
|
|
209
|
-
- **
|
|
210
|
-
- **
|
|
211
|
-
- **Model-visible ⇔ logged.** The plugin appends **no custom session event types**. Out-of-repo event types are not in the host's `KNOWN_SESSION_EVENT_TYPES`, so an unknown required event would make the session log unreadable after plugin removal (the host deliberately defers a registration surface for external plugins). All model-visible content therefore flows through host-logged surfaces: `tool/result` canonical values, `user/message` notices via `agent.inject`/`agent.followup`, the `command/run` + `command/done` lifecycle pair, and the `approval/asked` + `approval/decided` audit pair.
|
|
212
|
-
- **Pure presenters.** `presentCall`/`presentResult` are pure functions of `args` (+ the persisted `result.meta`), identical on live streaming and log replay. PR creation shows a generic card with the PR URL.
|
|
146
|
+
- **Permissions**: writes ride the official approval seam; nothing is re-implemented or bypassed. The plugin declares `network:outbound` and `filesystem:write` in its workshop manifest.
|
|
147
|
+
- **Data**: the review report lives in process memory keyed by job id; nothing durable is written to disk.
|
|
148
|
+
- **Session log**: the plugin adds no custom session event types; all model-visible content flows through host-logged surfaces (`tool/result`, `user/message`, `command/run`, `approval/asked`…).
|
|
213
149
|
|
|
214
|
-
##
|
|
150
|
+
## Security boundaries
|
|
215
151
|
|
|
216
|
-
-
|
|
217
|
-
-
|
|
218
|
-
-
|
|
219
|
-
-
|
|
220
|
-
-
|
|
221
|
-
-
|
|
222
|
-
- Rate limits: 429s are retried with backoff and the remaining quota is surfaced to the model on every result, including failures.
|
|
152
|
+
- **Approval, not enforcement.** Writes only produce `ask`/deny decisions on the official seam; the sandbox and approval systems remain the enforcement authorities.
|
|
153
|
+
- **Fail closed.** Missing approval answerer degrades to the strictest decision — never to silent pass-through.
|
|
154
|
+
- **The token never leaves the process.** It is read per operation and sent only in the Authorization header; never logged, rendered, injected, or surfaced in errors.
|
|
155
|
+
- **No writes outside approval.** `/pr create` never commits or pushes by itself; with `autoCommit: true`, the model performs those writes through the bash tool's own approval gate. The review job performs no writes; only `review_post` publishes, after approval.
|
|
156
|
+
- **Untrusted content is escaped and marked.** `formatPostBody` backtick- and HTML-escapes diff-derived file names, and external GitHub content (files, bodies, comments, search results) is marked as external in renders.
|
|
157
|
+
- **Bounded work and rate limits.** 429s are retried with backoff; the remaining quota is surfaced on every result, including failures.
|
|
223
158
|
|
|
224
|
-
##
|
|
159
|
+
## Known limitations
|
|
225
160
|
|
|
226
161
|
- **No custom session events** — deliberate (see Architecture); audit trails rely on the host's own event vocabulary.
|
|
227
|
-
- **Static analyzer by default** — deterministic rules (`src/review.ts`), zero tokens, reproducible. `reviewMode: "model"`
|
|
228
|
-
- **Jobs and records are process-local** — the review report lives in plugin memory keyed by job id
|
|
229
|
-
- **npm `latest` dist-tags are stale** —
|
|
230
|
-
- **CI / GitHub Action** — ships in this repository (v0.6.0): a composite action (`action.yml`) that reviews PRs, fixes CI, and writes the report; a polling review bot with idempotent inline comments; and a status-check gate. Every write stays approval-gated.
|
|
162
|
+
- **Static analyzer by default** — deterministic rules (`src/review.ts`), zero tokens, reproducible. `reviewMode: "model"` costs tokens and requires the `subagents` seam and a registered provider.
|
|
163
|
+
- **Jobs and records are process-local** — the review report lives in plugin memory keyed by job id; the record map is capped by `maxReviewRecords` (oldest settled records evict first).
|
|
164
|
+
- **npm `latest` dist-tags are stale** — install through the profile closure `dsh-base` provides; never bare `npm i @deepseek-ai/dsh-tools`.
|
|
231
165
|
|
|
232
|
-
##
|
|
166
|
+
## Development
|
|
233
167
|
|
|
234
168
|
```sh
|
|
235
|
-
pnpm install
|
|
236
|
-
pnpm
|
|
237
|
-
pnpm
|
|
238
|
-
pnpm
|
|
239
|
-
pnpm
|
|
169
|
+
pnpm install # node ^22.19 || >=24
|
|
170
|
+
pnpm run build # tsc --noEmitOnError → lib/
|
|
171
|
+
pnpm run prepare # self-contained git-install build (scripts/prepare.mjs)
|
|
172
|
+
pnpm run prepublishOnly # build + test before publishing
|
|
173
|
+
pnpm test # vitest run
|
|
174
|
+
pnpm run typecheck # tsc --noEmit
|
|
240
175
|
pnpm run check:readmes # cross-checks TOC anchors, tools, and config keys in all 5 READMEs
|
|
241
176
|
```
|
|
242
177
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
## 🗂 Repository layout
|
|
178
|
+
## Repository layout
|
|
246
179
|
|
|
247
180
|
```
|
|
248
181
|
src/index.ts plugin entry (name/inject/apply, applyWithDeps for tests)
|
|
@@ -262,15 +195,13 @@ cordis.patch.yml bundle patch (one insert row)
|
|
|
262
195
|
scripts/prepare.mjs self-contained git-install build
|
|
263
196
|
```
|
|
264
197
|
|
|
265
|
-
##
|
|
266
|
-
|
|
267
|
-
Recommended GitHub repository topics (set them in the repo settings — they power the [`dsh-plugin` topic page](https://github.com/topics/dsh-plugin) and the DSH plugin marketplaces):
|
|
198
|
+
## Topics
|
|
268
199
|
|
|
269
200
|
`dsh` · `dsh-plugin` · `deepseek-harness` · `github` · `pull-request` · `code-review` · `issue-tracker`
|
|
270
201
|
|
|
271
|
-
##
|
|
202
|
+
## Contributors
|
|
272
203
|
|
|
273
|
-
[
|
|
204
|
+
- [@PerryLink](https://github.com/PerryLink) — creator and maintainer: the GitHub tool surface, approval gate, background review jobs, CI composite action, review bot, status-check gate, and the five-language docs.
|
|
274
205
|
|
|
275
206
|
## PerryLink DSH Plugin Family
|
|
276
207
|
|
|
@@ -293,3 +224,7 @@ This project is one of the [15 DeepSeek Harness plugins](https://github.com/Perr
|
|
|
293
224
|
| **[dsh-github](https://github.com/PerryLink/dsh-github)** | GitHub PR/issues integration for DSH, every write gated by approval |
|
|
294
225
|
| [dsh-plugin-guide](https://github.com/PerryLink/dsh-plugin-guide) | Plugin-development knowledge base as an on-demand agent skill |
|
|
295
226
|
| [dsh-claude-move](https://github.com/PerryLink/dsh-claude-move) | Migrate Claude Code sessions, memory, skills and CLAUDE.md into DSH |
|
|
227
|
+
|
|
228
|
+
## License
|
|
229
|
+
|
|
230
|
+
[Apache License 2.0](LICENSE) © 2026 dsh-github contributors
|