Skip to content
dsh.fish
Bundle

dsh-pr-description

DSH native tool: analyze the current branch diff, generate a Conventional Commits PR title, motivation/scheme/testing/risk description and a self-review checklist, write PR_DESCRIPTION.md, and optionally open the PR via the gh CLI.

Source
988hj7tczd-oss
stars
1 stars
License
MIT
Updated
Updated yesterday

Readme

# dsh-pr-description

> [!IMPORTANT]
> **依赖前置:相邻 `dsh-src` 检出(`link:` 依赖)**
> 本项目在开发形态下使用 `link:` 依赖指向相邻的 DeepSeek Harness 源码检出(`dsh-src`),
> 与当前仓库保持同一父目录布局(`<parent>/dsh-src`)。克隆本仓库后:
> 1. 先把官方 `deepseek-ai/deepseek-harness` 检出到与本仓库同级的 `dsh-src/` 目录,并执行其 `pnpm install && pnpm run build`;
> 2. 再按下方「安装」一节执行本仓库的 `pnpm install --offline && pnpm build` 与测试。
> 发布到 npm 的版本会尽量把 `link:` 依赖替换为 registry 真实版本;无法替换的内部包保持 `link:`,见各包 README 说明。


DSH 原生工具:分析当前分支 diff,自动生成符合 **Conventional Commits** 的 PR 标题、动机/方案/影响/测试/风险五段描述与**自审清单**,输出 Markdown 到工作区并在会话内渲染;可选 `confirm` 交互确认与 `openPr` 直接调用 gh CLI 提 PR。

> 项目定位(2026-08 调研):DSH 社区已有大量「代码评审」,但「PR 描述自动生成」无人做。本插件只借鉴上游 `anthropics/claude-plugins-official` 评审类插件的**工作流顺序**(范围 → diff → 聚焦),文案与实现全部自写,License 为 MIT。

## 功能

- `pr_describe` 工具,流程对齐评审工作流:
  1. **确定范围**:`git diff --name-status <base>...HEAD`;`base` 缺省自动探测(`origin/HEAD` → `origin/main` → `origin/master` → `main` → `master` → `develop` → `HEAD~1`),探测失败给出结构化错误提示显式指定;
  2. **统计与归类**:新增/修改/删除文件数、`+/-` 行数;按 `docs / test / chore / feat / fix / refactor` 确定性归类(规则见下);
  3. **符号提取**:新增函数/类/导出(轻量正则,去重、上限 16);
  4. **生成 PR 文本**:`feat(scope): 动词短句` 标题 + 动机/方案(引用文件与符号)/影响范围/测试建议/风险与开放问题五段 + 自审清单(4 项);
  5. **confirm / openPr**:`confirm: true` 走 ask-user 交互确认,取消则不落盘;`openPr: true` 且 gh 可用时直接 `gh pr create --title --body-file`(不自动 push)。
- 结果写入 `PR_DESCRIPTION.md`(默认,可经 `output` / 配置 `outputFile` 修改)+ 会话内 Markdown 渲染。
- 解析失败(非 git 仓库 / 无提交 / 无差异 / base 不存在)返回带稳定 `code` 的结构化错误。
- BREAKING CHANGE 标注**当且仅当**检测到破坏性信号:`BREAKING CHANGE:` 注解、`package.json` 主版本提升、删除公开导出且同文件无同名新增。

> 说明:当前「动机/方案/影响/测试/风险」五段为**确定性模板拼装**(由 diff 统计、符号提取与破坏性信号直接填充文案),**未调用 LLM**;PROMPT §4.4 中「调用模型填充五段」尚未实现,如需语义润色请自行在生成后接入模型处理。

### 变更分类规则(确定性,可测试)

1. 全部为文档文件(`.md` / `docs/` / `README*`)→ `docs`
2. 全部为测试文件(`tests/` / `*.test.*` / `*.spec.*`)→ `test`
3. 全部为配置/CI 文件(`.github/` / `*.yml` / `.eslint*` 等)→ `chore`
4. 出现全新符号(function/class/export/type 且删除侧无同名声明)→ `feat`
5. 新增行含修复类关键词(fix/bug/crash 等)→ `fix`
6. 兜底 → `refactor`

## 安装与加载

两种挂载方式。随包发布的 `cordis.yml`(package.json 的 `dsh.bundle.patch`)为**生产模式**行名,已按已安装包可解析的说明符(裸包名)书写:

> **行名解析**:DSH loader 对 patch 内的行名按 profile 的 baseUrl 解析——相对路径锚定在
> `<DSH_HOME>/profiles/<name>/`(root config 所在目录),裸包名则从该目录的 node_modules 解析。
> 因此相对源码路径 `./src/index.ts` 安装后会指向不存在的 `<profile>/src/index.ts`,必须用裸包名或绝对路径。

### 生产:安装为 bundle 后以裸包名挂载

```sh
pnpm build                              # tsc → lib/(含 lib/types 声明归一化,见下)
dsh plugin --profile demo add ./dsh-pr-description
```

`dsh plugin add` 把本包安装进 profile 的 node_modules,并因 package.json 声明了 `dsh.bundle`
将其 `cordis.yml` 作为 patch 层加入;行名 `dsh-pr-description` 为裸包名,loader 按 profile 的
baseUrl 从已安装 node_modules 解析(`main` → `lib/index.js`)。

### 开发:热加载源码用绝对路径

不改随包发布的 `cordis.yml`,另写一个 overlay patch 并把行名指向源码绝对路径(同
`dsh-src/scratch-plugin/cordis.yml` 的写法):

```yaml
# cordis.dev.yml —— dev 热加载 overlay
- insert:
    - id: pr-describe
      name: '/abs/path/to/dsh-pr-description/src/index.ts'   # 绝对路径,不能写 ./src/index.ts
      config:
        locale: 'zh'
        defaultTitleStyle: 'conventional'
        outputFile: 'PR_DESCRIPTION.md'
```

```sh
dsh --patch ./cordis.dev.yml
```

loader 对 patch 内相对行名按 profile 的 baseUrl(而非 overlay 文件所在目录)解析,dev 模式必须写绝对路径。

## 用法(会话内示例)

```
分析当前分支的改动,用 pr_describe 生成 PR 描述并确认后写入
```

工具参数:

| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
| `workdir` | string | 配置 `workdir` 或进程 cwd | git 仓库目录 |
| `base` | string | 自动探测 | 对比基线 |
| `titleStyle` | string | `conventional` | `conventional` / `plain` |
| `confirm` | boolean | `false` | 生成前 ask-user 交互确认;取消不落盘 |
| `openPr` | boolean | `false` | gh 可用时直接提 PR;不可用则跳过并说明 |
| `output` | string | `PR_DESCRIPTION.md` | 输出文件(相对 workdir) |
| `locale` | string | `zh` | 模板语言 `zh` / `en` |

插件配置(`cordis.yml`):

```yaml
- insert:
    - id: pr-describe
      name: 'dsh-pr-description'
      config:
        locale: 'zh'
        defaultTitleStyle: 'conventional'
        outputFile: 'PR_DESCRIPTION.md'
        defaultBase: ''        # 留空 = 自动探测
        workdir: ''            # 留空 = 进程 cwd
```

## 开发

```sh
node tests/smoke.offline.mjs   # 零依赖离线冒烟(Node>=22.18 原生 TS strip + 真实 git fixture)
pnpm test:e2e                  # vitest fixture 仓库 e2e(需已安装 DSH 依赖)
pnpm build                     # tsc → lib/ + lib/types 相对导入归一化为 .js
```

代码结构:

```
src/index.ts                # 装配 + Config + 工具注册(Cordis 插件行)
src/tools/pr-describe.ts    # defineTool 定义(五阶段主流程)
src/diff-analysis.ts        # git diff 解析(纯函数)+ GitRunner seam + 编排
src/templates.ts            # 标题/五段/自审清单模板(zh/en,纯函数)
src/gh.ts                   # gh CLI 探测与可选提 PR(runner seam)
tests/smoke.offline.mjs     # 离线冒烟:真实 git fixture + 纯层断言
tests/smoke.e2e.ts          # vitest e2e:假 ctx + 真实 git,覆盖 confirm/错误/gh
```

设计要点:

- **受控执行**:所有 git/gh 调用以固定 argv 数组经 `ctx.subprocess`(`GITRunner` seam)执行,不拼接 shell 字符串,模型/用户输入永不进入命令行参数外的任何位置;
- **可测试性**:解析/分类/模板/gh 均为零依赖纯函数,离线冒烟可直接驱动;`ctx.get('userQuestions')` 为可选依赖,缺失时给出 `ASK_USER_UNAVAILABLE` 结构化错误;
- **生命周期**:`ctx.tools.register` 与所有 spawn 均随插件 Fiber 卸载自动清理(subprocess 服务持有进程树生命周期)。

## License

MIT。上游 `pr-review-toolkit` / `commit-commands` 为 Proprietary,本插件仅借鉴工作流顺序与模板结构,未复制其文案。

## 权限、失败边界与 DSH STORE 状态

- [PERMISSIONS.md](./PERMISSIONS.md):运行时读取面 / 命令面(固定 argv,非 shell)/ 写面 / 外部服务 / 失败边界 / 供应链 / 文件权限信号(无 chmod/chown、644、无 setuid/setgid)。
- [docs/store-evidence.md](./docs/store-evidence.md):一次性 Profile 安装 → 启动(工具注册清单)→ 卸载步骤、本地离线证据、待宿主补录真实运行记录说明,并逐项回应 DSH STORE 五类审查信号(仓库 canonical 匹配 / Node 声明 / 供应链 / 文件权限 / 命令权限)。
- STORE 复检由 dsh-safe-plugin-manager 每 3 小时自动执行;本仓库已按清单契约声明(package.json 的 `repository` / `engines.node` / `dsh.compatibility` / `dsh.permissions`)。

Install

dsh plugin --profile web add github:988hj7tczd-oss/dsh-pr-description

Profile: web

  • This package builds from source on install. pnpm will ask you to allow its build script — that is permission to run the package’s code on your machine, outside the agent sandbox. Only allow sources you trust.
  • This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.
Source