@liangnkang/issue-to-pr
v0.1.0
Published
AI agent skill: issue tracker → recon → approved plan → code fix → pull request, with human gates. Tracker- and host-agnostic.
Downloads
93
Maintainers
Readme
issue-to-pr
English | 中文
一个 AI agent skill,把 issue tracker 里的任务做成一个经过评审的 pull request,在关键位置留下人工审批门 —— 并且不预设你团队的任何约定。
跟 agent 说「fix PROJ-482」,它会先收集情报:issue 本身、完整的评论串、已有的分支和 PR、真正相关的代码、git 历史。然后要么告诉你缺什么,要么给你一份待批准的计划。只有你批准之后它才动代码。没有你同意,不会 commit、不会 push、不会开 PR、不会回写 tracker。
issue → 侦察 → 情报门 → 计划门 → 写代码 → 验证 → 评审 → 推送门 → (可选)PR → (可选)评论为什么重写
这是 jira-fix-skill 的彻底重写。前者能用,但把一个团队的约定写成了规则:分支永远是 feature/、commit 只有一种自定义格式、PR 正文固定三段、目标分支默认 develop、issue 状态永远不许改。对那个团队是好默认,对其他人则必须改 skill 源码才能用。
这里每一条都变成了配置,而真正值得保留的部分 —— 三道门、先侦察后判断、评审意见逐项升级 —— 原样留下。
支持范围
| | 已支持 | 契约就绪,尚未实现 |
|---|---|---|
| Tracker | Jira Cloud、Jira Server/Data Center、GitHub Issues | Linear、Azure Boards、YouTrack |
| Git 托管 | GitHub、GitHub Enterprise、GitLab(含自建) | Bitbucket、Azure DevOps |
| 工具链 | JS/TS(npm、pnpm、yarn、bun)、Python(uv、poetry、pipenv)、Go、Rust、Java、Elixir、Ruby、Swift、Make | |
| Agent | Cursor、Claude Code、Codex CLI,以及任何读 SKILL.md 的工具 | |
需要 Node 20+、git,以及对应托管平台的 gh 或 glab。GitLab 部分按官方 API 文档实现并有单测覆盖,但还没在真实实例上跑过。
三道门
- 情报门 —— issue 信息不足时,agent 明确说出缺什么、为什么需要,然后停下。它不猜。
- 计划门 —— 给你一份六段计划,你批准之前不写任何文件。
- 推送门 —— commit 之前你会看到 diff 统计、验证证据和确切的 commit message。
反馈轮次刻意跳过这三道门:issue 已经调查过、计划已经批准过、分支已经发布。而判断你是否处于反馈轮次,靠的是仓库状态而不是你的措辞 —— agent 会先查已有分支和 PR,因为「继续修 PROJ-123」这句话对两种情况都成立,猜错就等于跳过了你依赖的审批。
其他性质
- 除非你配置,绝不改 issue 状态
- 绝不自动 stash;工作区不干净就停下来问
- 绝不静默解决 merge 冲突
- 推送门之前一定做代码评审,项目里有 review skill 就用它
- PR 默认是 draft,
pr create永远不会开出重复 PR - fork 仓库的 PR 会开到上游,并明确告知
- 附件会被下载并真的看过;看不到的图片会被报告成情报缺口,绝不靠猜来描述
安装
npx @liangnkang/issue-to-pr # 选择安装位置
npx @liangnkang/issue-to-pr --all --yes # 装到所有检测到的位置,无需交互
npm i -g @liangnkang/issue-to-pr # 可选:让 `i2pr` 进入 PATHskill 自包含且零依赖,装在哪都能直接跑。配置放在 skill 目录之外,升级不会被覆盖。
配置
i2pr config init --id acme --type jira \
--site https://acme.atlassian.net --email [email protected] \
--token-env ACME_TOKEN --projects PROJ,DFT
cd ~/work/web && i2pr repo detect && i2pr toolchain detect每个仓库提交一份 .issue-to-pr.json:
{
"repo": { "targetBranch": "main" },
"commands": { "test": "pnpm test", "lint": "pnpm run lint" },
"conventions": {
"branch": { "typeMap": { "default": "feature" } },
"commit": { "template": "{type}({scope}): {key} {module} - {subject}" },
"pr": { "draft": false }
}
}i2pr config show 会打印每个生效值以及它来自哪个文件,所以任何反直觉的配置都能一条命令解释清楚。
分层
从低到高:内置默认 → ~/.config/issue-to-pr/config.json(站点与凭据来源)→ <repo>/.issue-to-pr.json(提交进仓库、团队共享)→ <repo>/.issue-to-pr.local.json(gitignore)→ I2PR_* 环境变量 → --set 参数。
这就是一份安装能同时服务 main 仓库、develop 仓库、pnpm 仓库和 pytest 仓库的原因,也是两个 Jira 站点能共存的原因。
仓库级文件只允许设置约定、命令和目标分支。凭据字段和 tracker 站点在那里会被拒绝并报告 —— 仓库配置是随代码一起来的,可信度不会高于代码本身。
凭据
这个工具不写任何凭据。Git 托管的 token 由 gh/glab 保管。Tracker 优先走已连接的 MCP(完全不需要 token);否则用 tokenEnv 指向环境变量,或用 credentialCommand 调你自己的密钥库。
使用
正常说话即可。
| 你说 | 会发生什么 | |---|---| | 「show my issues」 | 列出分配给你的未完成 issue | | 「fix PROJ-482」 | 侦察 → 情报门 → 计划 → 你批准 → 写代码 → 验证 → 评审 → 推送门 | | 「看下最新的评论」 | 读这个分支 PR 和 issue 上的新反馈,然后开始修 | | (贴一个 PR 链接) | 同上,针对那个 PR —— 在任何目录都能用 | | 「plan for PROJ-482」 | 只做侦察和计划,绝不动代码 |
CLI
文本进、文本出,所有命令支持 --format json,永不交互。
i2pr config show
i2pr repo detect
i2pr toolchain detect
i2pr branches --key PROJ-482
i2pr issue list --limit 10
i2pr issue get PROJ-482 --download /tmp/shots
printf 'Fixed: …\nPR: …\n' | i2pr issue comment PROJ-482 --body-file -
i2pr pr find --source fix/PROJ-482-actions
i2pr pr create --title "fix(client): PROJ-482 keep actions visible" --source fix/PROJ-482-actions --body-file -
i2pr pr feedback --since "$(git log -1 --format=%cI)"
i2pr convention branch --key PROJ-482 --type Bug --summary "Message actions unreachable"
i2pr convention commit --key PROJ-482 --type Bug --scope client --subject "keep the action row visible"
i2pr convention check-comment --body-file -i2pr --help 看完整命令。错误带稳定错误码(CONFIG_MISSING、AUTH_REQUIRED、PR_NOT_FOUND、RATE_LIMITED 等)且经过脱敏,token 和带凭据的 URL 不会出现在输出里。
正确性要点
这些是容易做错的地方,都有测试钉住:
- 时间戳按时刻比较。
git log --format=%cI输出…+09:00,而托管平台输出…Z。按字符串比较会静默丢掉真实的评审意见。 - 分支查找按 token 边界匹配。 查
PROJ-1不能命中PROJ-12,否则 agent 会误判「已经有人开始做了」,然后 merge 一个无关分支。 - 分页一定走到底。 被截断的反馈列表和「评审者什么都没说」长得一模一样。
- 已解决的会话和自己发的评论会被过滤;当 review threads API 不可用时,
resolved是unknown而不是false。 - 默认分支检测忽略配置,所以让用户确认「检测到的分支」不会变成确认他自己早先写下的值。
- 包管理器由 lockfile 决定。 偏好某一个,会在所有用别的包管理器的仓库里跑错工具。
ORDER BY priority DESC才是最高优先级在前;ASC会把最低优先级排到最上面。
npm test # 106 个测试,不联网、不调 CLI、不碰磁盘开发
lib/errors.js 稳定错误码、输出脱敏
lib/time.js 时间戳归一化
lib/process.js 可注入的子进程访问
lib/config/ 分层配置与来源追踪
lib/git-host/ 检测、GitHub、GitLab
lib/tracker/ Jira、GitHub Issues、ADF 渲染
lib/conventions/ 分支、commit、PR 正文、评论模板
lib/toolchain/ test/lint/format 探测
bin/i2pr.js 薄 CLI
SKILL.md 策略层
references/ 给 agent 的渐进披露文档
docs/DESIGN.md 分层、契约、默认值取舍每个 provider 的子进程 runner 或 fetch 都是注入进来的,所以整个测试套件离线运行。加一个新 provider 只需实现 docs/DESIGN.md 里的契约,策略层不用动。
License
MIT
