diff --git a/skills/gitlink-code-review/REFERENCE.md b/skills/gitlink-code-review/REFERENCE.md index 0011473..1145d5d 100644 --- a/skills/gitlink-code-review/REFERENCE.md +++ b/skills/gitlink-code-review/REFERENCE.md @@ -50,23 +50,34 @@ gitlink-cli pr +files --id --format json | `files[].isDeleted` | boolean | 是否删除文件 | | `files[].isRenamed` | boolean | 是否重命名 | -### 获取 PR Diff +### 获取 PR Diff(`pr +version-diff`,替代已移除的 `pr +diff`) + +`pr +diff` 已移除(与 `file` 冗余)。先取补丁集版本,再看版本差异: ```bash -gitlink-cli pr +diff --id --format json +# 1) 取 patchset version_id +gitlink-cli pr +versions --id --format json +# 2) 看该版本的逐行 diff +gitlink-cli pr +version-diff --id --version-id [--file ] --format json ``` -**返回字段说明:** +**`pr +versions` 返回字段:** | 字段 | 类型 | 说明 | |------|------|------| -| `files_count` | int | 文件总数 | -| `total_addition` | int | 总新增行数 | -| `total_deletion` | int | 总删除行数 | -| `files[].sections[].lines[].leftIdx` | int | 原文件行号 | -| `files[].sections[].lines[].rightIdx` | int | 新文件行号 | -| `files[].sections[].lines[].type` | int | 1=未变, 2=新增, 3=删除, 4=统计信息 | -| `files[].sections[].lines[].content` | string | 行内容 | +| `data.versions[].id` | int | **patchset 版本 ID(version-diff 用这个)** | + +**`pr +version-diff` 返回字段:** + +| 字段 | 类型 | 说明 | +|------|------|------| +| `data.file_nums` | int | 文件总数 | +| `data.files[].name` | string | 文件名 | +| `data.files[].addition` / `deletion` | int | 该文件增/删行数 | +| `data.files[].sections[].lines[].content` | string | 行内容(含 `@@ ...` hunk 头) | +| `data.files[].sections[].lines[].type` | int | **2=新增, 3=删除, 4=hunk 头(`@@`);据此筛出变更行** | + +> ⚠️ `--file ` 过滤不稳定,建议整份取后客户端按 `files[].name` 筛。需读文件全文用 `file +get --ref --path <文件>`。 --- @@ -100,6 +111,53 @@ gitlink-cli pr +list --state --format json --- +## 评审与评论命令(代码审查写入) + +### `pr +review` — 提交评审(首选) + +```bash +gitlink-cli pr +review --id --status --content "<报告>" [--commit ] [--dry-run] --format json +``` + +| 参数 | 说明 | +|------|------| +| `-i, --id` | PR 编号 | +| `-s, --status` | **评审状态:`common`(普通评论)/ `approved`(批准)/ `rejected`(拒绝,即 Request changes)**,默认 `common` | +| `-c, --content` | 评审内容(Markdown,放整体审查报告) | +| `-m, --commit` | 可选,挂到具体 commit SHA | +| `--dry-run` | **预览不提交(审查必用)** | + +> 状态映射:报告含 Critical → `rejected`;仅 Warning/Suggestion → `common`;无问题 → `approved`。**不要用 GitHub 风格的 `event:"COMMENT"`**,GitLink 用 `--status`。 + +### `pr +create-comment` — 行内评审评论 + +```bash +gitlink-cli pr +create-comment --id --path <文件路径> --line <行号> --body "<意见>" --format json +``` + +| 参数 | 说明 | +|------|------| +| `-i, --id` | PR 编号 | +| `-p, --path` | 文件路径 | +| `-l, --line` | **文件中的行号**(非 diff 补丁位置;注意 import/头注释偏移) | +| `-b, --body` | 评论内容 | + +> 行号不确定时**不要发**——并入 `pr +review --content` 总报告,或改用 `pr +comment`。 + +### `pr +comment` — 普通评论(不绑行) + +```bash +gitlink-cli pr +comment --id --body "<评论>" --format json +``` + +> 以 journal 形式挂在 PR 下,不绑定文件行。是行内评论失败时的安全 fallback。 + +### `pr +reviews` — 列出已有评审(复审时用) + +```bash +gitlink-cli pr +reviews --id [--status ] --format json +``` + ## Issue 相关 API ### 获取 Issue 列表 diff --git a/skills/gitlink-code-review/SKILL.md b/skills/gitlink-code-review/SKILL.md index 3294536..f7897cf 100644 --- a/skills/gitlink-code-review/SKILL.md +++ b/skills/gitlink-code-review/SKILL.md @@ -1,7 +1,7 @@ --- name: gitlink-code-review -version: 1.0.0 -description: "智能代码审查:获取 PR 变更、分析代码质量、自动生成 Review 评论与摘要报告。当用户需要审查 Pull Request、检查代码质量或生成审查报告时触发。" +version: 1.2.0 +description: "当用户需要对 GitLink 上的 Pull Request 做代码审查时触发:获取 PR 变更/Diff、按严重程度输出结构化 Review 意见、并(经确认后)把评审评论提交到 PR。适用于收到 PR Review 请求、需要批量审查 PR、为 PR 自动生成审查报告等场景。" metadata: requires: bins: ["gitlink-cli"] @@ -11,311 +11,201 @@ metadata: # gitlink-code-review(智能代码审查) **CRITICAL — 开始前必须先阅读 [`../gitlink-shared/SKILL.md`](../gitlink-shared/SKILL.md),其中包含认证、权限处理和 API 注意事项。** -**CRITICAL — 所有写入/删除操作前,务必先确认用户意图。** +**CRITICAL — 所有写入/删除操作前,务必先确认用户意图;提交 Review 会通知 PR 相关人,必须先出报告→用户确认→dry-run→再提交。** **CRITICAL — GitLink 操作只能用 `gitlink-cli`。禁止用 `gh`(GitHub CLI)操作 GitLink 资源。`gh` 仅适用于 GitHub 平台。** -> **前置条件:** 先阅读 [`../gitlink-shared/SKILL.md`](../gitlink-shared/SKILL.md) 了解认证和全局参数。 +## 核心原则 + +1. **用 Shortcut,不用 Raw API**:提交评审用 `pr +review`,行内评论用 `pr +create-comment`,普通评论用 `pr +comment`。不要用 GitHub 风格的 Raw API(`event:"COMMENT"` / `position` 等字段 GitLink 不支持)。 +2. **建议优先,确认后提交**:先把结构化审查报告交给用户确认,**禁止未经确认直接提交 Review/评论**。尤其禁止用 `--yes` 绕过确认,除非用户明确说「直接提交/不用确认」。 +3. **严重程度分级驱动结论**:有 Critical → 评审状态用 `rejected`(Request changes);仅 Suggestion/Positive → `common`;无问题 → `approved`。 +4. **安全红线零容忍**:硬编码密钥、SQL/命令注入、XSS、路径遍历、不安全反序列化必须标 Critical。 ## 工作流概览 -本 Skill 提供一套完整的 AI 驱动代码审查工作流,覆盖从获取 PR 变更到生成审查报告的全过程。不需要额外的 CLI Shortcuts——现有 `gitlink-cli` 命令 + AI Agent 的分析能力即可完成。 - -| 阶段 | 操作 | AI Agent 角色 | -|------|------|--------------| -| ① 获取上下文 | 拉取 PR 详情、变更文件、Diff | 执行 CLI 命令采集数据 | -| ② 分析代码 | 检查每个文件的变更 | 逐文件审查,标记问题 | -| ③ 结构化反馈 | 按严重程度分级输出审查意见 | 生成分级 Review 评论 | -| ④ 提交评论 | 发表 Review 到 PR | 通过 API 提交 | -| ⑤ 生成报告 | 输出审查摘要 | 生成 Markdown 摘要 | +| 阶段 | 操作 | 命令 | +|------|------|------| +| ① 获取上下文 | PR 详情 / 变更文件 / Diff | `pr +view` / `pr +files` / `pr +diff` | +| ② 逐文件分析 | 按语言检查项审查 | (AI 分析) | +| ③ 出审查报告 | 按严重程度分级,**等用户确认** | (无写入) | +| ④ dry-run 预览 | 用户确认后,预览评审 | `pr +review --dry-run` | +| ⑤ 提交评审 | 用户再次确认后提交 | `pr +review`(去 `--dry-run`) | +| ⑥ 行内评论(可选) | 针对具体行追加 | `pr +create-comment --path --line` | --- ## 详细工作流 -### 工作流 1:PR 代码审查 - -**场景**:收到 PR Review 请求后,进行完整代码审查。 - -#### Step 1:获取 PR 上下文 +### Step 1:获取 PR 上下文 ```bash -# 获取 PR 详情 +# PR 详情 gitlink-cli pr +view --id --format json -# 获取变更文件列表 +# 变更文件列表(含增删行数、是否新建) gitlink-cli pr +files --id --format json -# 获取 Diff 内容(含变更行号和代码上下文) -gitlink-cli pr +diff --id --format json +# Diff 内容(先取补丁集版本,再看版本差异;pr +diff 已移除) +gitlink-cli pr +versions --id --format json # 拿 version_id +gitlink-cli pr +version-diff --id --version-id --format json # 逐行 diff ``` -#### Step 2:逐文件分析 +> `--id` 是 PR 编号(web URL 中的编号)。Diff 在 `files[].sections[].lines[]`,`type`:2=新增、3=删除、4=hunk 头(`@@ ...`);按文件分组逐文件分析,大型 PR 分段处理。 +> +> ⚠️ **实测(2026-06-21)**:`pr +diff` 已被移除(与 `file` 冗余),由 `pr +version-diff` 替代。`--file ` 过滤不稳定,建议整份取 diff 后客户端按文件名筛。需要读某文件全文时用 `file +get --ref --path <文件>`。 -对每个变更文件,根据文件类型执行针对性检查: +### Step 2:逐文件分析 -**Python 文件检查项:** -- 语法与导入:未使用的 import、循环导入、wildcard import -- 代码规范:PEP 8 风格偏离、过长行(>88 chars)、命名规范 -- 安全:硬编码密钥、SQL 注入风险、`eval()`/`exec()` 使用 -- 性能:不必要的循环、缺少缓存、N+1 查询 -- 错误处理:裸 `except`、吞异常、缺少 finally +对每个变更文件,按语言执行针对性检查: -**JavaScript/TypeScript 文件检查项:** -- 安全:`innerHTML` 直接赋值、`eval()` 使用 -- 类型安全:`any` 滥用、缺失类型定义 -- 性能:不必要的 re-render、大对象深拷贝 -- 异步:未处理的 Promise、缺少 error boundary -- 依赖:已废弃 API 使用 +**Python**:未用/循环 import;PEP8 偏离与过长行;硬编码密钥、SQL 注入、`eval()`/`exec()`;裸 `except`、吞异常;N+1 查询。 +**JS/TS**:`innerHTML` 直赋、`eval()`;`any` 滥用;未处理 Promise;废弃 API。 +**Go**:未检查的 error return、panic 滥用;goroutine 泄漏、缺 sync;未关闭 file/conn;导出标识符缺注释。 +**通用**:硬编码配置/密钥/URL;边界条件缺失;圈复杂度过高;魔法数字;DRY 违反;注释过时;测试覆盖不足。 -**Go 文件检查项:** -- 错误处理:未检查的 error return、panic 滥用 -- 并发:goroutine 泄漏、缺少 sync 保护 -- 资源管理:未关闭的 file/conn、defer 使用 -- 命名:导出标识符缺少注释、变量 shadowing +### Step 3:出审查报告(建议,不写入) -**通用检查项:** -- 硬编码的配置值、密钥、URL -- 缺少或错误的边界条件检查 -- 过于复杂的函数(圈复杂度高) -- 魔法数字(未命名的常量) -- 重复代码(DRY 违反) -- 缺少或过时的注释 -- 测试覆盖不足 - -#### Step 3:生成结构化审查结果 - -按以下 Severity 分级输出: +按严重程度分级输出,**此阶段不执行任何写入**: ```markdown ## PR # 代码审查报告 ### 🔴 Critical(必须修改) -- <问题描述> — <文件>:<行号> +- <问题> — <文件>:<行号> > <修改建议> -### 🟡 Warning(建议修改) -- <问题描述> — <文件>:<行号> - > <修改建议> +### 🟡 Warning(建议修改) / 🔵 Suggestion(可选优化) / ✅ Positive(值得肯定) +- ... -### 🔵 Suggestion(可选优化) -- <问题描述> — <文件>:<行号> - > <修改建议> - -### ✅ Positive(值得肯定) -- <做得好的地方> +### 总体结论 +<评审状态建议:rejected / common / approved;是否阻塞合并> ``` -#### Step 4:提交 Review 评论 +**等待用户确认**:用户没说「确认/提交」前停在 Step 3。**禁止用 `--yes` 自行推进。** + +### Step 4:dry-run 预览(用户确认报告后) + +根据报告的严重程度选择评审状态,dry-run 预览(不实际提交): + +| 报告含 Critical | 评审状态 | 含义 | +|-----------------|----------|------| +| 是 | `rejected` | Request changes,阻塞合并 | +| 否,仅 Warning/Suggestion | `common` | 普通评审评论 | +| 无问题 | `approved` | 批准合并 | ```bash -# 方式 1:提交整体 Review -gitlink-cli api POST /:owner/:repo/pulls/:id/reviews --body '{ - "body": "## 审查结果\n\n### 🔴 Critical\n...\n\n### 🟡 Warning\n...\n\n总体评价:...", - "event": "COMMENT" -}' - -# 方式 2:在特定行添加内联评论(逐条提交) -gitlink-cli api POST /:owner/:repo/pulls/:id/reviews --body '{ - "body": "这里存在安全风险:用户输入未经转义直接拼接到 SQL 查询中,存在注入风险。建议使用参数化查询。", - "event": "COMMENT", - "commit_id": "", - "path": "src/query.py", - "position": 42 -}' +gitlink-cli pr +review --id \ + --status \ + --content "<把审查报告 Markdown 作为 content>" \ + --dry-run --format json ``` -> **注意:** `event` 参数支持 `COMMENT`(普通评论)和 `APPROVE`(批准)。对于需要修改的问题,使用 `COMMENT`。 +> `--content` 放整体审查报告(Markdown)。`--commit ` 可选,把评审挂到具体 commit。核对 dry-run 输出无误。 -#### Step 5:生成审查摘要 +### Step 5:提交评审(用户确认 dry-run 后) -审查完成后,输出 Markdown 摘要供用户查阅: +去掉 `--dry-run` 正式提交: -```markdown -## 📋 审查摘要 — PR # +```bash +gitlink-cli pr +review --id <pr_id> \ + --status <common|approved|rejected> \ + --content "<审查报告>" \ + --format json +``` -| 指标 | 数据 | -|------|------| -| 审查文件数 | <n> | -| 变更行数 | +<add> / -<del> | -| Critical 问题 | <n> | -| Warning | <n> | -| Suggestion | <n> | +### Step 6:行内评论(可选,针对具体行) -### 主要发现 -1. **[Critical]** <最严重的问题> -2. **[Warning]** <次要问题> -3. **[Suggestion]** <优化建议> +需要把某条意见精准挂在某一行时,用 `pr +create-comment`: -### 总体评价 -<整体评估:代码质量、审查通过建议> +```bash +gitlink-cli pr +create-comment --id <pr_id> \ + --path <文件路径> --line <行号> \ + --body "<针对该行的意见>" --format json +``` ---- -*由 gitlink-code-review Skill 自动生成* +> ⚠️ `--line` 是**文件中的行号**。Diff 输出给的可能是补丁内位置,需换算为文件真实行号(注意文件头部 import/license 偏移)。**若行号不确定,不要盲目发**——把该意见并入 Step 5 的 `--content` 总报告,或改用 `pr +comment`(普通评论,不挂行)。 +> +> ⚠️ **实测(2026-06-21)**:`pr +create-comment --line` 会返回 `ok:true`,但返回的 `line_code` 为 `null`,**评论未真正锚定到该行**(仅挂在文件级)。因此优先用 `pr +review --content` 提交总报告;行内评论不可靠时改用 `pr +comment`。 + +```bash +# 普通评论(挂在 PR 下,不绑定行;行号不确定时的安全 fallback) +gitlink-cli pr +comment --id <pr_id> --body "<评论>" --format json ``` --- -### 工作流 2:仓库代码健康度扫描 +## 评审状态与严重程度的映射 -**场景**:对仓库整体代码质量进行评估,不依赖 PR。 +| 报告内容 | `--status` | 合并建议 | +|---------|-----------|---------| +| 含任何 Critical | `rejected` | 阻塞,修复后复审 | +| 仅 Warning/Suggestion | `common` | 可合并,建议跟进 | +| 全部 Positive / 无问题 | `approved` | 可合并 | -```bash -# 1. 获取仓库信息 -gitlink-cli repo +info --owner <owner> --repo <repo> --format json +## 安全红线(必须标 Critical) -# 2. 获取仓库文件列表(遍历关键目录) -gitlink-cli api GET /:owner/:repo/sub_entries --query 'filepath=src&ref=master' -gitlink-cli api GET /:owner/:repo/sub_entries --query 'filepath=tests&ref=master' - -# 3. 获取关键文件内容 -gitlink-cli api GET /:owner/:repo/raw/master/README.md -gitlink-cli api GET /:owner/:repo/raw/master/.gitignore -gitlink-cli api GET /:owner/:repo/raw/master/.eslintrc.js # 或类似配置 -gitlink-cli api GET /:owner/:repo/raw/master/package.json # 或 go.mod, Cargo.toml - -# 4. 获取语言统计和贡献者 -gitlink-cli api GET /:owner/:repo/languages -gitlink-cli api GET /:owner/:repo/contributors -``` - -**健康度检查清单:** - -| 检查项 | 标准 | 评分依据 | -|--------|------|----------| -| 文档完整性 | 有 README、CONTRIBUTING、CHANGELOG | 文件是否存在、内容质量 | -| 许可证 | 有 LICENSE 文件 | 是否存在、是否合规 | -| CI 配置 | 有 CI 配置(.github/workflows, Jenkinsfile 等) | 文件是否存在 | -| 代码规范 | 有 linter 配置 | eslint/prettier/ruff/pylint 等 | -| 测试覆盖 | 有 test 目录或测试文件 | 测试文件比例 | -| 依赖管理 | 依赖文件完整且无已知漏洞 | package-lock/go.sum/poetry.lock | -| Issue 健康度 | Issue 有分类标签、响应及时 | 通过 Issue 列表分析 | - -**输出格式:** - -```markdown -## 🏥 仓库健康度报告 — <owner>/<repo> - -### 总体评分:<⭐x/5> - -| 维度 | 状态 | 评分 | 建议 | -|------|:----:|:----:|------| -| 📖 文档 | ✅/⚠️/❌ | ☆☆☆☆☆ | <建议> | -| 📜 许可证 | ✅/⚠️/❌ | ☆☆☆☆☆ | <建议> | -| 🔧 CI/CD | ✅/⚠️/❌ | ☆☆☆☆☆ | <建议> | -| 🎨 代码规范 | ✅/⚠️/❌ | ☆☆☆☆☆ | <建议> | -| 🧪 测试覆盖 | ✅/⚠️/❌ | ☆☆☆☆☆ | <建议> | -| 📦 依赖安全 | ✅/⚠️/❌ | ☆☆☆☆☆ | <建议> | -| 🐛 Issue 管理 | ✅/⚠️/❌ | ☆☆☆☆☆ | <建议> | - -### 关键发现 -1. <最需要改进的问题> -2. <次要问题> -3. <做得好的方面> - -### 改进路线图 -- **紧急(本周):** ... -- **短期(本月):** ... -- **长期(本季度):** ... -``` - ---- - -### 工作流 3:批量 Issue Triage + 自动分配 - -**场景**:对新 Issue 进行自动分类、标签分配和责任人推荐。 - -```bash -# 1. 获取未标记的 Issue -gitlink-cli issue +list --state open --format json - -# 2. 逐个分析 Issue 内容 -gitlink-cli issue +view --id <issue_id> --format json - -# 3. 根据内容智能分类 -# 分析标题和描述后,通过 Raw API 打标签 -gitlink-cli api POST /:owner/:repo/issues/:id --body '{ - "issue_tag_ids": [<tag_id>], - "done_ratio": 0, - "subject": "<原始标题>", - "description": "<原始描述>" -}' -``` - -**分类规则参考:** - -| Issue 关键词 | 推荐标签 | 优先级 | -|-------------|----------|:------:| -| bug, 错误, 失败, crash, 崩溃 | bug | 🔴 High | -| feature, 新增, 建议, 希望 | enhancement | 🔵 Low | -| 安全, 漏洞, 权限, 泄露 | security | 🔴 High | -| 性能, 慢, 卡顿, 优化 | performance | 🟡 Medium | -| 文档, README, 注释 | documentation | 🔵 Low | -| question, 如何, 怎么, 请问 | question | 🟡 Medium | -| 测试, test, 覆盖率 | testing | 🔵 Low | - ---- - -## Raw API 参考 - -代码审查相关的 GitLink API 端点: - -```bash -# 获取 PR 详情 -gitlink-cli api GET /:owner/:repo/pulls/:id --format json - -# 获取 PR 变更文件列表 -gitlink-cli api GET /:owner/:repo/pulls/:id/files --format json - -# 获取 PR Diff -gitlink-cli api GET /:owner/:repo/pulls/:id/diff --format json - -# 提交 PR Review -gitlink-cli api POST /:owner/:repo/pulls/:id/reviews --body '{"body":"...","event":"COMMENT"}' - -# 获取仓库文件列表 -gitlink-cli api GET /:owner/:repo/sub_entries --query 'filepath=<path>&ref=<branch>' - -# 获取仓库语言统计 -gitlink-cli api GET /:owner/:repo/languages --format json - -# 获取贡献者列表 -gitlink-cli api GET /:owner/:repo/contributors --format json - -# 获取仓库动态 -gitlink-cli api GET /:owner/:repo/activity --format json -``` +- 硬编码的密钥 / Token / 密码 / 数据库连接串 +- SQL / NoSQL 注入(用户输入直接拼接进查询) +- 命令注入(shell 命令拼接用户输入) +- 路径遍历(用户输入直接用于文件路径) +- XSS(未转义的用户输入直接渲染,如 `innerHTML`) +- 不安全的反序列化 ## 代码审查最佳实践 -### 审查原则 +1. **先大局后细节**:先理解 PR 目的与整体变更范围,再逐文件审查。 +2. **关注行为而非风格**:风格问题交给 linter/formatter。 +3. **提供可操作的建议**:不只指出问题,给出具体修改方案。 +4. **肯定好的代码**:清晰命名、完善测试、良好设计给予正面反馈。 +5. **控制评论量**:最严重的 3–5 个问题比 20 个小问题更有价值。 -1. **先大局后细节**:先理解 PR 的目的和整体变更范围,再逐文件审查 -2. **关注行为,而非风格**:自动化工具(linter/formatter)能处理的风格问题优先交给工具 -3. **提供可操作的建议**:不只是指出问题,要给出具体的修改方案 -4. **肯定好的代码**:发现好的设计、清晰的命名、完善的测试时给予正面反馈 -5. **控制评论量**:避免信息过载——最严重的 3-5 个问题比 20 个小问题更有价值 +## 命令速查 -### 安全红线 +```bash +# 获取上下文 +gitlink-cli pr +view --id <pr_id> --format json +gitlink-cli pr +files --id <pr_id> --format json +gitlink-cli pr +versions --id <pr_id> --format json # 拿 version_id +gitlink-cli pr +version-diff --id <pr_id> --version-id <vid> --format json # 逐行 diff(替代已移除的 pr +diff) -以下问题必须标记为 **Critical**,不得忽略: +# 提交评审(首选) +gitlink-cli pr +review --id <pr_id> --status <common|approved|rejected> --content "<报告>" [--commit <sha>] [--dry-run] -- 硬编码的密钥 / Token / 密码 -- SQL / NoSQL 注入漏洞 -- 命令注入(shell 命令拼接) -- 路径遍历(用户输入直接用于文件路径) -- 不安全的反序列化 -- XSS(未转义的用户输入直接渲染) +# 行内评论(绑定文件+行;行号不确定时勿用) +gitlink-cli pr +create-comment --id <pr_id> --path <path> --line <n> --body "<意见>" -### 输出规范 +# 普通评论(不绑行;安全 fallback) +gitlink-cli pr +comment --id <pr_id> --body "<评论>" -- 始终使用 `--format json` 获取结构化数据 -- 审查报告输出为 **Markdown 格式**,便于直接粘贴到 PR 评论 -- 涉及文件/行号时使用精准引用,方便定位 -- 批量操作前使用 `--dry-run` 预检 +# 查看已有评审(复审时用) +gitlink-cli pr +reviews --id <pr_id> --format json +``` + +## Raw API 参考 + +评审相关操作**优先用上述 Shortcut**。Shortcut 未覆盖时才用 Raw API,且字段需符合 GitLink(**不是** GitHub 的 `event:"COMMENT"`/`position`): + +```bash +# 列出已有评审 +gitlink-cli api GET /:owner/:repo/pulls/:id/reviews --format json +``` + +> 字段说明详见 [`REFERENCE.md`](REFERENCE.md)。 + +## 红线与常见错误 + +- ❌ **用 GitHub 风格 Raw API 提交评审**(`event:"COMMENT"`、`position`、`commit_id`+`path`)——GitLink 用 `pr +review --status` 与 `pr +create-comment --path --line`。 +- ❌ **未经用户确认就提交 Review/评论**——必须 报告→确认→dry-run→提交。 +- ❌ **用 `--yes` 绕过确认门**——除非用户明确要求「直接提交」。 +- ❌ **行号不确定却发 `+create-comment --line`**——会挂错行或被拒;改并入总报告或用 `+comment`。 +- ❌ **有 Critical 却用 `--status common/approved`**——Critical 必须配 `rejected`。 +- ❌ **用 `gh` 操作 GitLink**——只用 `gitlink-cli`。 +- 所有命令加 `--format json` 便于解析;输出为 `{ok, data, meta}` envelope。 ## 注意事项 -- PR Review 提交后会通知所有关注该 PR 的参与者,评论内容请保持专业 -- `pr +diff` 输出可能很大(大型 PR),Agent 应分段处理 -- API 的 PR files 和 diff 接口有频率限制,避免短时间内重复请求 -- 对于 draft PR(草稿),应提示用户先将其标记为 Ready for Review +- Review/评论提交后会通知 PR 所有相关人,内容请专业、可操作。 +- 大型 PR 的 diff 可能非常大,按文件分段处理,避免一次性塞满上下文。 +- `pr +diff` / `+files` 接口有频率限制,避免短时间内重复请求。 +- 对 draft PR,提示用户先标记为 Ready for Review 再审查。 +- 审查范围限于 PR 本身(代码审查);仓库整体健康度、Issue 分拣等场景见各自专用 Skill,不在本 Skill 范围。 diff --git a/skills/gitlink-code-review/examples/pr-review-workflow.md b/skills/gitlink-code-review/examples/pr-review-workflow.md index 2028acc..82a5f7a 100644 --- a/skills/gitlink-code-review/examples/pr-review-workflow.md +++ b/skills/gitlink-code-review/examples/pr-review-workflow.md @@ -113,17 +113,50 @@ gitlink-cli pr +diff --id 42 --format json - 有类型注解,代码可读性好 ``` -### Step 5:提交 Review +### Step 5:dry-run 预览(用户确认报告后) + +报告含 2 个 Critical,评审状态取 `rejected`(Request changes)。先 dry-run 预览,**不实际提交**: ```bash -# 提交整体 Review 评论 -gitlink-cli api POST /Gitlink/forgeplus/pulls/42/reviews --body '{ - "body": "## PR #42 代码审查报告\n\n### 🔴 Critical\n\n1. **JWT Secret 硬编码** — `src/config.py:15`\n JWT_SECRET 硬编码在源码中。建议使用 `os.getenv(\"JWT_SECRET\")`。\n\n2. **SQL 注入风险** — `src/auth/login.py:42`\n 直接拼接用户输入到 SQL 查询。建议使用参数化查询。\n\n### 🟡 Warning\n\n1. **密码明文存储** — 建议使用 bcrypt 哈希处理。\n\n### 总体评价\n\n代码整体结构清晰,测试覆盖良好。建议修复 Critical 问题后合并。", - "event": "COMMENT" -}' +gitlink-cli pr +review --id 42 \ + --status rejected \ + --content "## PR #42 代码审查报告 + +### 🔴 Critical +1. **JWT Secret 硬编码** — src/config.py:15。建议 os.getenv(\"JWT_SECRET\")。 +2. **SQL 注入风险** — src/auth/login.py:42。建议参数化查询。 + +### 🟡 Warning +1. **密码明文存储** — 建议使用 bcrypt 哈希处理。 + +### 总体评价 +代码整体结构清晰,测试覆盖良好。建议修复 Critical 问题后合并。" \ + --dry-run --format json ``` -### Step 6:输出审查摘要 +→ 核对预览无误,请用户二次确认。 + +### Step 6:提交评审(用户确认 dry-run 后) + +去掉 `--dry-run` 正式提交: + +```bash +gitlink-cli pr +review --id 42 --status rejected --content "<同上审查报告>" --format json +``` + +### Step 7:行内评论(可选,针对具体行) + +把 Critical 意见精准挂到对应行(行号取文件真实行号,注意 import/头注释偏移;不确定则并入上面的总报告): + +```bash +gitlink-cli pr +create-comment --id 42 --path src/config.py --line 15 \ + --body "Critical: JWT_SECRET 硬编码,存在泄露风险。改用 os.getenv(\"JWT_SECRET\")。" --format json + +gitlink-cli pr +create-comment --id 42 --path src/auth/login.py --line 42 \ + --body "Critical: SQL 注入风险,用户输入直接拼接。改用参数化查询。" --format json +``` + +### Step 8:输出审查摘要 ```markdown ## 📋 审查摘要 — PR #42 feat: add user authentication module @@ -159,6 +192,12 @@ gitlink-cli pr +files --id <id> --format json # 获取 Diff gitlink-cli pr +diff --id <id> --format json -# 提交 Review -gitlink-cli api POST /:owner/:repo/pulls/:id/reviews --body '{"body":"...","event":"COMMENT"}' +# 提交评审(首选;Critical→rejected / 仅建议→common / 无问题→approved) +gitlink-cli pr +review --id <id> --status <common|approved|rejected> --content "<审查报告>" [--dry-run] + +# 行内评论(绑定文件+行;行号不确定时勿用,改用 +comment 或并入 --content) +gitlink-cli pr +create-comment --id <id> --path <path> --line <n> --body "<意见>" + +# 普通评论(不绑行) +gitlink-cli pr +comment --id <id> --body "<评论>" ``` diff --git a/skills/gitlink-issue-triage/REFERENCE.md b/skills/gitlink-issue-triage/REFERENCE.md new file mode 100644 index 0000000..708d462 --- /dev/null +++ b/skills/gitlink-issue-triage/REFERENCE.md @@ -0,0 +1,167 @@ +# gitlink-issue-triage API 参考 + +> 分拣相关的 gitlink-cli 命令返回字段说明。先阅读 [`../gitlink-shared/SKILL.md`](../gitlink-shared/SKILL.md) 了解 envelope `{ok, data, meta}` 与全局参数。 + +## 前置:ID 解析命令 + +分拣写入参数(`--label`/`--assignee`/`--priority`)都吃 **ID**,必须先解析。 + +### `label +list` — 标签(name → id) + +```bash +gitlink-cli label +list --format json +``` + +| 字段 | 类型 | 说明 | +|------|------|------| +| `data.issue_tags[].id` | int | **标签 ID(写入时传这个)** | +| `data.issue_tags[].name` | string | 标签名称(GitLink 默认为中文:缺陷/功能/疑问/文档/任务…) | +| `data.issue_tags[].color` | string | 颜色(hex) | +| `data.issue_tags[].description` | string | 标签说明 | + +### `label +assigners` — 可指派人(login → id) + +```bash +gitlink-cli label +assigners --format json +``` + +| 字段 | 类型 | 说明 | +|------|------|------| +| `data.assigners[].id` | int | **用户 ID(`--assignee` 传这个)** | +| `data.assigners[].login` | string | 登录名 | +| `data.assigners[].name` | string | 显示名/角色(如「后端组」) | + +### `label +priorities` — 优先级(name → id) + +```bash +gitlink-cli label +priorities --format json +``` + +| 字段 | 类型 | 说明 | +|------|------|------| +| `data.priorities[].id` | int | 优先级 ID(`--priority` 传这个) | +| `data.priorities[].name` | string | 名称(如 高/正常/低) | + +### `label +create` — 补建缺失标签(确认后) + +```bash +gitlink-cli label +create --name <name> --color <hex_without_#> --format json +``` + +| 参数 | 说明 | +|------|------| +| `-n, --name` | 标签名称(必填) | +| `-c, --color` | 颜色 hex(不带 #,如 `ff0000`),可选 | + +--- + +## 分拣主体命令 + +### `issue +list` — 列出 Issue + +```bash +gitlink-cli issue +list --state open --format json +``` + +| 字段 | 类型 | 说明 | +|------|------|------| +| `data.issues[].number` | int | **Issue 编号(web URL 中的编号,写入用这个)** | +| `data.issues[].id` | int | Issue 内部 ID | +| `data.issues[].name` / `subject` | string | 标题 | +| `data.issues[].tags` | array | 已打标签(**为空 = 未分拣,需处理**) | +| `data.issues[].assigners` | array | 已指派人 | +| `data.issues[].priority` | object | 优先级 `{id, name}` | +| `data.issues[].author` | object | 作者 `{login, name}` | + +> ⚠️ `--state` 仅影响统计计数,返回列表可能含所有状态。**幂等筛选**:保留 `tags` 为空的 Issue,跳过已打标签的。 + +### `issue +view` — 查看详情(语义分析用) + +```bash +gitlink-cli issue +view --number <n> --format json +``` + +| 字段 | 类型 | 说明 | +|------|------|------| +| `data.issue.number` | int | Issue 编号 | +| `data.issue.subject` | string | 标题 | +| `data.issue.description` | string | **描述(语义分析的主要输入)** | +| `data.issue.status_id` | int | 状态 ID | +| `data.issue.tags` | array | 已打标签(`[{id,name,color}]`,**为空 = 未分拣**) | +| `data.issue.priority` | object | 优先级 | + +> 写入参数用 `--number`(web 编号),不是内部 `id`。 + +### `issue +batch-update` — 批量更新(同标签批量场景) + +```bash +gitlink-cli issue +batch-update \ + --numbers <a,b,c> \ + --label <单个id> \ + [--assignee <id>] [--priority <id>] \ + [--dry-run] --format json +``` + +| 参数 | 说明 | +|------|------| +| `-n, --numbers` | 逗号分隔的 Issue 编号 | +| `-l, --label` | 标签 **ID**;⚠️ **集合式**——把传入的标签集合打到 `--numbers` 里**每一个** Issue,**非按位置对应** | +| `-a, --assignee` | 指派人 **ID** | +| `-m, --milestone` / `-p, --priority` | 里程碑 / 优先级 ID | +| `-s, --state` | open / closed / 数字 status_id | +| `--dry-run` | **预览不写入** | +| `--from` | 从 CSV 读编号(大批量场景) | + +> ⚠️ **实测**:`--label a,b,c` 会把 {a,b,c} 全部打到这批每个 Issue(集合式)。因此**仅用于多个 Issue 共用同一(组)标签**;各 Issue 标签不同时改用下方 Raw API。`--dry-run` 输出含 `updates.issue_tag_ids`(扁平数组,印证集合式)。 + +### `issue +update` — 单个 Issue 更新 + +```bash +gitlink-cli issue +update --number <n> --assignee <id> --format json +``` + +| 参数 | 说明 | +|------|------| +| `-n, --number` | Issue 编号 | +| `-l, --label` | ⚠️ **实测不可用**:CLI 发单数 `issue_tag_id` 被平台忽略,标签打不上。打标签改用 Raw API `issue_tag_ids` | +| `-a, --assignee` | 指派人 **ID** | +| `-t, --title` / `-b, --body` | 新标题/描述(更新会自动保留原 subject/description,不会清空) | +| `-s, --state` / `-m, --milestone` / `-p, --priority` | 状态/里程碑/优先级 | + +### `issue +comment` — 添加引导评论 + +```bash +gitlink-cli issue +comment --number <n> --body "<评论内容>" --format json +``` + +| 参数 | 说明 | +|------|------| +| `-n, --number` | Issue 编号 | +| `-b, --body` | 评论内容(支持 Markdown) | + +--- + +## Raw API 兜底 + +Shortcut 未覆盖时用 Raw API。**Issue 更新需先 GET 拿到当前 `subject`/`description` 再带上提交**,否则可能清空描述(见 gitlink-shared 已知坑)。 + +```bash +# 打标签(issue_tag_ids 为标签 ID 数组) +gitlink-cli api PATCH /:owner/:repo/issues/:number --body '{ + "issue_tag_ids": [<tag_id>, ...], + "subject": "<原标题>", + "description": "<原描述>" +}' +``` + +| 字段 | 说明 | +|------|------| +| `issue_tag_ids` | 标签 **ID 数组**(不是名称) | +| `subject` / `description` | 必须回带原值,防止清空 | + +## 数据获取最佳实践 + +1. **始终 `--format json`** 便于解析。 +2. 写入参数一律传 **ID**:标签/指派人/优先级都先解析为 ID。 +3. **幂等**:`issue +list` 后客户端筛 `labels` 为空的,避免重复分拣。 +4. 批量前先 `--dry-run` 预览,核对 `--numbers` 与 `--label`/`--assignee` 位置对应。 diff --git a/skills/gitlink-issue-triage/SKILL.md b/skills/gitlink-issue-triage/SKILL.md index ad8e695..b227ea7 100644 --- a/skills/gitlink-issue-triage/SKILL.md +++ b/skills/gitlink-issue-triage/SKILL.md @@ -1,7 +1,7 @@ --- name: gitlink-issue-triage -version: 1.0.0 -description: "Issue 自动分拣:根据 Issue 内容自动分类、打标签、分配责任人、添加引导评论。当用户需要自动处理新提交的 Issue 时触发。" +version: 1.2.0 +description: "当用户需要批量处理新提交的 GitLink Issue(自动分类、打标签、分配责任人、添加引导评论)时触发。适用于 Issue 积压无人分流、新 Issue 缺少分类标签、需要按类别指派维护者等场景。" metadata: requires: bins: ["gitlink-cli"] @@ -11,77 +11,207 @@ metadata: # gitlink-issue-triage(Issue 自动分拣) **CRITICAL — 开始前必须先阅读 [`../gitlink-shared/SKILL.md`](../gitlink-shared/SKILL.md),其中包含认证、权限处理和 API 注意事项。** -**CRITICAL — 所有 Shortcuts 在执行写入/删除操作前,务必先确认用户意图。** +**CRITICAL — 所有写入/删除操作前,务必先确认用户意图;分拣属于批量写入,必须先出方案→用户确认→dry-run 预览→再执行。** +**CRITICAL — GitLink 操作只能用 `gitlink-cli`。禁止用 `gh`(GitHub CLI)操作 GitLink 资源。`gh` 仅适用于 GitHub 平台。** -## 说明 +## 核心原则 -本 Skill 组合多个 gitlink-cli 命令,实现 Issue 的自动化分类和处理流程: +1. **语义分类为主,关键词表为辅**:你是 AI Agent,价值在于读懂 Issue 意图(如「登录后白屏、控制台报 500」即使没有「bug」字眼也应判为 Bug)。下方关键词表只是兜底/加速,不要退化成正则匹配。 +2. **建议优先,确认后写入**:先输出「分拣方案表」给用户确认,**禁止未经确认直接打标签/改指派人**。尤其禁止用 `--yes` 绕过确认,除非用户明确说「直接应用/不用确认」。 +3. **幂等**:只处理「尚未分拣」的 Issue(无标签或仅有默认标签),避免对已分拣 Issue 重复操作。 +4. **打标签用 Raw API,批量仅限同标签**:实测 `issue +update --label` 不可用、`+batch-update --label` 是集合式(整组标签打到每个 Issue),故各 Issue 不同标签时用 Raw API `issue_tag_ids`(详见 Step 5);仅当多 Issue 共用同一标签时才用 `+batch-update`。 -1. 获取新提交的 Issue 列表 -2. 根据 Issue 内容(标题 + 描述)自动判断类别 -3. 为 Issue 打上对应标签、分配责任人 -4. 添加引导评论 +## 工作流概览 -## 依赖的 Shortcuts +| 阶段 | 操作 | 命令 | +|------|------|------| +| ① 解析 ID(必做前置) | 取仓库标签/可指派人/优先级,建立 名称→ID 映射 | `label +list` / `label +assigners` / `label +priorities` | +| ② 取未分拣 Issue | 拉取 open Issue,客户端筛掉已打标签的 | `issue +list` | +| ③ 语义分析 | 逐个读标题+描述,判类别/标签/责任人/评论 | `issue +view` | +| ④ 出方案 | 输出「分拣方案表」,等用户确认 | (无写入) | +| ⑤ 打标签 | 用户确认后,逐 Issue 用 Raw API 打标签(不同标签);同标签可批量 | `api PATCH .../issues/:n` / `+batch-update` | +| ⑥ 引导评论 | 为每个 Issue 添加分类引导评论 | `issue +comment` | -| Shortcut | 用途 | -|----------|------| -| `issue +list` | 获取待处理的 Issue 列表 | -| `issue +view` | 查看 Issue 详细内容 | -| `issue +update` | 修改 Issue 状态/标签 | -| `issue +comment` | 添加评论 | -| `label +list` | 查看可用标签 | -| `user +info` | 查询用户信息 | +--- -## 处理流程 +## 详细工作流 +### Step 1:解析 ID(**必做前置,切勿跳过**) + +GitLink 的标签、指派人、优先级参数都吃 **ID 而非名称**。先拉取并建立映射: + +```bash +# 标签:name → id(返回在 data.issue_tags[];标签名因仓库而异,如某仓库为 缺陷/功能/疑问/文档…) +gitlink-cli label +list --format json + +# 可指派人:login → id(如 alice→101) +gitlink-cli label +assigners --format json + +# 优先级:name → id(数值因仓库而异,如某仓库为 低→1/正常→2/高→3/紧急→4,以实际输出为准) +gitlink-cli label +priorities --format json ``` -1. issue +list --state open → 获取所有打开的 Issue -2. issue +view --number {id} → 查看 Issue 详情 -3. 分析 subject + description → 判断 Issue 类别 -4. label +list → 查看可用标签 -5. issue +update --label {label} → 打标签 -6. issue +comment --body "..." → 添加引导评论 + +> 没有 ID 映射就无法正确执行 Step ⑤⑥。若目标标签不存在,见 Step 4「补建标签」。 + +### Step 2:取未分拣 Issue(幂等筛选) + +```bash +# 拉取所有 open Issue +gitlink-cli issue +list --state open --format json ``` +筛选规则(客户端过滤):**保留尚未打标签的 Issue**(`tags` 字段为空),跳过已有分类标签的,避免重复分拣。 + +### Step 3:语义分析 + +对每个待分拣 Issue: + +```bash +gitlink-cli issue +view --number <issue_number> --format json +``` + +读取 `subject` + `description`,按下方「分类规则参考」判断类别、推荐标签、推荐责任人角色、引导评论要点。 + +### Step 4:出「分拣方案表」(建议,不写入) + +输出一张表给用户确认,**此阶段不执行任何写入**: + +```markdown +| # | 标题 | 判定类别 | 标签(id) | 责任人(id) | 评论文案要点 | +|---|------|---------|----------|-----------|-------------| +| 12 | 登录后白屏 500 | Bug | bug(1) | bob(102) | 请补浏览器/复现步骤/后端日志 | +| 13 | 希望支持暗黑模式 | Feature | enhancement(2) | alice(101) | 请确认范围:全局/页面级、是否跟随系统 | +``` + +**补建标签(可选)**:若方案需要的标签在 `label +list` 中不存在(如缺 `bug`),不要静默跳过,也**不要擅自创建**——在方案表中标注「标签缺失」,待用户确认后用 `gitlink-cli label +create --name bug` 创建,再继续。 + +**等待用户确认**:用户没说「确认/执行」前,停在 Step 4。**禁止用 `--yes` 自行推进。** + +### Step 5:打标签(用户确认方案后) + +> ⚠️ **实测要点(2026-06-15 端到端验证)**: +> - `issue +update --label <id>` **不可用**——CLI 发送单数 `issue_tag_id`,平台忽略,标签打不上。 +> - `issue +batch-update --label a,b,c` 是**集合式**:把 `{a,b,c}` 打到 `--numbers` 里**每一个** Issue,**不是**按位置对应。仅适合「多个 Issue 共用同一(组)标签」。 +> - 可用的打标签方式是 Raw API 的 `issue_tag_ids`(复数数组)。 + +**情形 A:各 Issue 标签不同(最常见)→ 逐 Issue 用 Raw API(已验证):** + +```bash +gitlink-cli api PATCH /:owner/:repo/issues/<number> --body '{ + "issue_tag_ids": [<标签id>], + "subject": "<原标题>", + "description": "<原描述>" +}' +``` + +`issue_tag_ids` 是数组,**整体替换**该 Issue 的标签集;务必回带 `subject`/`description`,否则描述会被清空(见 gitlink-shared 已知坑)。 + +**情形 B:多个 Issue 共用同一标签 → 批量(先 dry-run 再执行):** + +```bash +# dry-run 预览(同一标签打到这批所有 Issue) +gitlink-cli issue +batch-update --numbers <a,b,c> --label <单个id> --dry-run --format json +# 核对后去掉 --dry-run 正式执行 +``` + +**指派人**:`issue +update --number <n> --assignee <user_id>`(`user_id` 来自 `label +assigners`)。若 `label +assigners` 为空(如个人仓库无可指派成员),**留空并在方案表注明**,不要乱指派。 + +### Step 6:引导评论 + +为每个 Issue 添加分类引导评论(语气专业,包含分类理由 + 需要补充的信息): + +```bash +gitlink-cli issue +comment --number 12 --body "已自动分拣为 **Bug**,转交 @bob。 +为加快定位,请补充:运行环境、复现步骤、浏览器控制台与后端日志。维护者会尽快处理。" +``` + +--- + ## 分类规则参考 -| 类别 | 标题关键词 | 建议标签 | 建议负责人 | -|------|-----------|---------|-----------| -| Bug | 错误、失败、异常、bug、crash、报错 | bug | 项目维护者 | -| 功能需求 | 建议、希望、需要、feature、支持 | enhancement | PM | -| 文档 | 文档、README、文档缺失、拼写 | documentation | 文档负责人 | -| 问题咨询 | 请问、怎么、如何、help、question | question | 社区支持 | -| 性能 | 慢、卡顿、性能、优化、performance | performance | 核心开发者 | +### 类别判定(语义优先,关键词兜底) -## 使用示例 +| 类别 | 语义信号 | 关键词兜底 | 建议标签 | 责任人角色 | +|------|---------|-----------|----------|-----------| +| Bug | 运行时报错、崩溃、行为异常、阻断主流程 | 错误/失败/异常/crash/报错/500/白屏 | bug | 后端或前端(按错误来源) | +| 功能需求 | 希望新增能力、改进现有行为 | 建议/希望/需要/feature/支持 | enhancement | PM / 对应模块开发 | +| 文档 | 文档缺失/错误/拼写 | 文档/README/拼写 | documentation | 文档负责人 | +| 问题咨询 | 询问用法、求助 | 请问/怎么/如何/help/question | question | 社区支持 / 文档 | +| 性能 | 慢、卡顿、资源占用 | 慢/卡顿/性能/优化/performance | performance | 核心开发者 | + +> 上表「建议标签」是语义类别名,**实际标签名以 `label +list` 为准**——GitLink 默认标签是中文(缺陷/功能/疑问/文档/任务…),需先把类别映射到仓库实际标签的 ID 再打。 + +### 角色 → 默认责任人映射(需用 `label +assigners` 的实际 ID 替换) + +| 角色 | 何时指派 | +|------|---------| +| 后端 | 服务端错误、API、数据库相关 | +| 前端 | UI、样式、浏览器端错误 | +| PM | 需求范围、优先级决策 | +| 文档 | 文档/问答类 | +| 核心开发者 | 性能、架构、安全 | + +> 实际指派时,把「角色」替换为 `label +assigners` 中对应的 **user_id**。若角色无对应成员,**留空并在方案表注明**,不要乱指派。 + +--- + +## 命令速查 ```bash -# 1. 获取所有打开的 Issue -gitlink-cli issue +list --owner myuser --repo myrepo --state open --format json +# 前置:解析 ID +gitlink-cli label +list --format json # 标签 name→id +gitlink-cli label +assigners --format json # 可指派人 login→id +gitlink-cli label +priorities --format json # 优先级 name→id +gitlink-cli label +create --name <name> --color <hex> # 补建缺失标签(确认后) -# 2. 查看某个 Issue 的详细内容 -gitlink-cli issue +view --owner myuser --repo myrepo --number 5 --format json +# 分拣主体 +gitlink-cli issue +list --state open --format json # 取未分拣(客户端筛 tags 为空的) +gitlink-cli issue +view --number <n> --format json # 读详情做语义分析(标签字段为 tags) -# 3. 查看仓库可用标签 -gitlink-cli label +list --owner myuser --repo myrepo +# 打标签(已验证可用): +# - 各 Issue 不同标签 → 逐个 Raw API(issue_tag_ids 整体替换) +gitlink-cli api PATCH /:owner/:repo/issues/<n> --body '{"issue_tag_ids":[<id>],"subject":"<原>","description":"<原>"}' +# - 多 Issue 共用同一标签 → 批量(集合式,先 --dry-run) +gitlink-cli issue +batch-update --numbers <a,b,c> --label <单个id> --dry-run -# 4. 为 Issue 打标签(假设判断为 bug) -gitlink-cli issue +update --owner myuser --repo myrepo --number 5 --state open - -# 5. 添加分类引导评论 -gitlink-cli issue +comment --owner myuser --repo myrepo --number 5 --body "感谢提交 Issue!已自动分类为 **Bug**,请补充以下信息: - -- 运行环境(操作系统、版本) -- 复现步骤 -- 期望行为与实际行为 - -项目维护者会尽快处理。" +gitlink-cli issue +comment --number <n> --body "<引导评论>" # 引导评论 +gitlink-cli issue +update --number <n> --assignee <user_id> # 指派人(user_id 来自 label +assigners) ``` +> ⚠️ `issue +update --label` 与 `+batch-update --label a,b,c`(多标签)均不可靠,详见红线。 + +--- + +## Raw API 参考 + +打标签的**主要可用方式**是 Raw API(Shortcut 的 `--label` 不可靠,见红线)。务必回带 `subject`/`description` 防清空: + +```bash +# 打标签(issue_tag_ids 为标签 ID 数组,整体替换该 Issue 标签集) +gitlink-cli api PATCH /:owner/:repo/issues/:number --body '{ + "issue_tag_ids": [<tag_id>, ...], + "subject": "<原标题>", + "description": "<原描述>" +}' +``` + +> 字段说明详见 [`REFERENCE.md`](REFERENCE.md)。 + +--- + +## 红线与常见错误 + +- ❌ **未经用户确认就打标签/指派**——必须方案表→确认→执行。 +- ❌ **用 `--yes` 绕过确认门**——除非用户明确要求「直接应用」。 +- ❌ **用 `issue +update --label` 打标签**——实测 CLI 发单数 `issue_tag_id` 被平台忽略,标签打不上;改用 Raw API `issue_tag_ids`(Step 5)。 +- ❌ **用 `+batch-update --label a,b,c` 给不同 Issue 打不同标签**——它是集合式,会把 {a,b,c} 全打到每个 Issue;仅用于多 Issue 共用同一标签。 +- ❌ **把标签名称当 ID 传**——必须先用 `label +list` 解析为 ID(返回在 `data.issue_tags[]`,标签名以实际为准)。 +- ❌ **重复分拣已分类 Issue**——Step 2 客户端筛掉 `tags` 非空的。 +- ❌ **用 `gh` 操作 GitLink**——只用 `gitlink-cli`。 +- 所有命令加 `--format json` 便于解析;输出为 `{ok, data, meta}` envelope。 + ## 注意事项 -- 每次操作前先列出当前待处理的 Issue,评估数量。 -- 添加评论前先确认 Issue 内容,避免误分类。 -- 标签名称需要先在项目中确认是否存在,不存在则跳过。 -- 分配责任人前需确认该用户是否为项目成员。 +- 分拣是批量写入,评论会通知 Issue 相关人,内容请专业、可操作。 +- `issue +list` 的 `--state` 仅影响统计计数,列表可能含全部状态,需客户端二次过滤。 +- 若 Issue 描述信息不足以判定类别,在方案表标注「信息不足,建议先发评论索取复现信息」,不要强行分类。 diff --git a/skills/gitlink-issue-triage/examples/triage-workflow.md b/skills/gitlink-issue-triage/examples/triage-workflow.md index 01cba44..9bc7a23 100644 --- a/skills/gitlink-issue-triage/examples/triage-workflow.md +++ b/skills/gitlink-issue-triage/examples/triage-workflow.md @@ -1,81 +1,188 @@ -# Issue 自动分拣完整工作流示例 +# Issue 批量自动分拣完整工作流示例 -**场景**:项目收到一个新 Issue,需要自动判断类别、打标签、添加引导评论。 +**场景**:仓库 `z2_cc/gitlink-cli` 积压了一批未分类的 open Issue,需要批量分流:自动判定类别、打标签、指派责任人、添加引导评论。 + +> 本示例遵循 SKILL.md 的核心原则:**语义分类为主、建议优先确认后写入、幂等、批量为主**。所有写入操作都经过「方案→确认→dry-run→执行」四步。 ## 前置条件 -- `gitlink-cli` 已安装并登录 +- `gitlink-cli` 已安装并登录(`gitlink-cli auth status` 正常) - 对目标仓库有写入权限 +- 已阅读 [`../../gitlink-shared/SKILL.md`](../../gitlink-shared/SKILL.md) -## 工作流步骤 +--- -### Step 1:查看待处理的 Issue +## Step 1:解析 ID(建立 名称→ID 映射) + +```bash +gitlink-cli label +list --format json +gitlink-cli label +assigners --format json +gitlink-cli label +priorities --format json +``` + +**`label +list` 输出示例:** +```json +{ + "ok": true, + "data": { "labels": [ + {"id": 1, "name": "bug"}, + {"id": 2, "name": "enhancement"}, + {"id": 3, "name": "documentation"}, + {"id": 4, "name": "question"}, + {"id": 5, "name": "performance"} + ]} +} +``` + +**`label +assigners` 输出示例:** +```json +{ + "ok": true, + "data": { "assigners": [ + {"id": 101, "login": "alice", "name": "前端组"}, + {"id": 102, "login": "bob", "name": "后端组"}, + {"id": 103, "login": "carol", "name": "文档组"} + ]} +} +``` + +→ 建立映射:标签 `bug→1, enhancement→2, question→4`;指派人 `alice→101, bob→102, carol→103`。 + +## Step 2:取未分拣 Issue(客户端筛掉已打标签的) ```bash gitlink-cli issue +list --owner z2_cc --repo gitlink-cli --state open --format json ``` -**输出示例:** +筛出**尚未打标签**的 3 个(已分类的跳过,保证幂等): + +| number | subject | labels | +|--------|---------|--------| +| 12 | 登录后页面白屏,控制台报 500 | (空) | +| 13 | 希望能支持暗黑模式 | (空) | +| 14 | 请问怎么配置 webhook? | (空) | + +## Step 3:语义分析(逐个读详情) + +```bash +gitlink-cli issue +view --owner z2_cc --repo gitlink-cli --number 12 --format json +``` + ```json { - "issues": [ - { - "number": 10, - "subject": "登录页面报错:500 Internal Server Error", - "status_id": 1, - "author": {"login": "newuser"} - } - ] + "ok": true, + "data": { "issue": { + "number": 12, + "subject": "登录后页面白屏,控制台报 500", + "description": "输入账号密码点登录后页面直接白屏,浏览器控制台显示 500 Internal Server Error。Chrome 120 / macOS。" + }} } ``` -### Step 2:查看 Issue 详细内容 +**语义判定(注意 #12 没有「bug」字眼,靠语义识别):** +- **#12**:500 + 阻断登录主流程 → **Bug**;500 是服务端响应 → 后端 bob +- **#13**:「希望支持暗黑模式」→ **功能需求 enhancement**;UI/样式 → 前端 alice +- **#14**:「请问怎么配置 webhook」→ **问题咨询 question**;答疑 → 文档 carol -```bash -gitlink-cli issue +view --owner z2_cc --repo gitlink-cli --number 10 --format json +## Step 4:出「分拣方案表」(建议,不写入,等用户确认) + +``` +分拣方案(共 3 个 Issue,请确认后我将 dry-run 预览): + +| # | 标题 | 类别 | 标签(id) | 责任人(id) | +|-----|----------------------|----------|-----------------|-------------| +| 12 | 登录后白屏 500 | Bug | bug(1) | bob(102) | +| 13 | 希望支持暗黑模式 | Feature | enhancement(2) | alice(101) | +| 14 | 请问怎么配置 webhook | Question | question(4) | carol(103) | + +引导评论将分别请求:#12 复现步骤/后端日志;#13 主题范围确认;#14 直接答复+文档化。 +确认执行吗?(回复「确认」我进入 dry-run 预览;如需调整请指出) ``` -### Step 3:分析 Issue 内容判断类别 +> ⏸️ **停在此处等用户确认。禁止用 `--yes` 自行推进。** -根据标题和描述中的关键词判断: +## Step 5:打标签(用户确认方案后) -| 关键词 | 类别 | -|--------|------| -| 报错、错误、bug | Bug | -| 建议、希望 | 功能需求 | -| 文档 | 文档 | -| 请问、怎么 | 问题咨询 | - -### Step 4:添加分类评论 +> ⚠️ 各 Issue 标签不同,**用 Raw API 逐个打**(实测 `issue +update --label` 不可用、`+batch-update --label` 是集合式,见 SKILL.md 红线)。务必回带 `subject`/`description` 防清空。 ```bash -gitlink-cli issue +comment --owner z2_cc --repo gitlink-cli --number 10 --body "感谢提交 Issue!已自动分类为 **Bug**。 - -请补充以下信息以便排查: -- 运行环境(操作系统、浏览器版本) -- 复现步骤 -- 错误截图或日志 - -项目维护者会尽快处理。" +# #12 → bug(1) +gitlink-cli api PATCH /:owner/:repo/issues/12 --body '{ + "issue_tag_ids": [1], "subject": "登录后页面白屏,控制台报 500", + "description": "输入账号密码点登录后页面直接白屏,控制台显示 500 Internal Server Error。Chrome 120/macOS。" +}' +# #13 → enhancement(2) +gitlink-cli api PATCH /:owner/:repo/issues/13 --body '{ + "issue_tag_ids": [2], "subject": "希望能支持暗黑模式", "description": "希望加暗黑主题切换。" +}' +# #14 → question(4) +gitlink-cli api PATCH /:owner/:repo/issues/14 --body '{ + "issue_tag_ids": [4], "subject": "请问怎么配置 webhook?", "description": "想把推送事件通知到群机器人。" +}' ``` -### Step 5:确认处理结果 +> 多个 Issue **共用同一标签**时,可改用批量:`issue +batch-update --numbers <a,b,c> --label <单个id> --dry-run` → 去 `--dry-run`。 +> 指派人:`issue +update --number <n> --assignee <user_id>`(`user_id` 来自 `label +assigners`;无可指派人则留空)。 + +**验证打标结果:** ```bash -gitlink-cli issue +view --owner z2_cc --repo gitlink-cli --number 10 --format json +gitlink-cli issue +view --number 12 --format json # data.issue.tags 应为 [{"id":1,"name":"bug"}] +``` + +## Step 6:引导评论(逐个添加) + +```bash +# #12 Bug +gitlink-cli issue +comment --owner z2_cc --repo gitlink-cli --number 12 \ + --body "已自动分拣为 **Bug**,转交 @bob。为加快定位,请补充:运行环境、稳定复现步骤、浏览器控制台与后端对应时间点的报错日志。" + +# #13 Feature +gitlink-cli issue +comment --owner z2_cc --repo gitlink-cli --number 13 \ + --body "已自动分拣为 **enhancement**,转交 @alice。落地前请确认范围:① 全局暗黑主题还是特定页面;② 是否跟随系统 prefers-color-scheme;③ 配色基准。" + +# #14 Question +gitlink-cli issue +comment --owner z2_cc --repo gitlink-cli --number 14 \ + --body "已自动分拣为 **question**,转交 @carol。快速回答:Webhook 在「仓库设置 → Webhooks」新增,填回调 URL、选触发事件,GitLink 会向该 URL 发 POST。完整字段说明将补充到 docs/。" ``` --- -## 完整命令速览 +## 命令速览 ```bash -# 1. 获取待处理 Issue -gitlink-cli issue +list --state open +# 1. 解析 ID +gitlink-cli label +list --format json +gitlink-cli label +assigners --format json -# 2. 查看详情 -gitlink-cli issue +view --number <id> +# 2. 取未分拣 Issue(客户端筛无标签的) +gitlink-cli issue +list --state open --format json -# 3. 添加分类评论 -gitlink-cli issue +comment --number <id> --body "<评论内容>" +# 3. 语义分析 +gitlink-cli issue +view --number <n> --format json + +# 4. 出方案表 → 用户确认(不写入) + +# 5. 打标签:各 Issue 不同标签 → 逐个 Raw API(issue_tag_ids 整体替换) +gitlink-cli api PATCH /:owner/:repo/issues/<n> --body '{"issue_tag_ids":[<id>],"subject":"<原>","description":"<原>"}' +# 多 Issue 共用同一标签 → 批量(先 --dry-run) +gitlink-cli issue +batch-update --numbers <a,b,c> --label <单个id> --dry-run + +# 6. 引导评论 +gitlink-cli issue +comment --number <n> --body "<评论>" ``` + +## 退化场景:单个 Issue + +只需分拣一个 Issue 时: + +```bash +# 打标签(Raw API;+update --label 实测不可用) +gitlink-cli api PATCH /:owner/:repo/issues/<n> --body '{"issue_tag_ids":[<id>],"subject":"<原标题>","description":"<原描述>"}' +# 指派人(可选) +gitlink-cli issue +update --number <n> --assignee <user_id> +# 引导评论 +gitlink-cli issue +comment --number <n> --body "<评论>" +``` + +同样遵循「方案→确认→执行」,不要直接 `--yes`。 diff --git a/skills/gitlink-shared/SKILL.md b/skills/gitlink-shared/SKILL.md index d1f9d33..478d007 100644 --- a/skills/gitlink-shared/SKILL.md +++ b/skills/gitlink-shared/SKILL.md @@ -109,6 +109,9 @@ gitlink-cli auth login | PR 合并需要 `do` 参数 | `pr +merge` 需传 `do` 字段指定合并方式(merge/rebase/squash) | `pr +merge` 已内置处理 | | PR 列表 state 过滤 | `--state` 参数仅影响统计计数,返回列表可能包含所有状态 | 需通过 `pull_request_status` 字段客户端过滤:0=open, 1=merged, 2=closed | | PR 创建需要代码差异 | 分支内容必须与目标分支不同,否则拒绝创建 | 需要先在分支上有实际提交 | +| **PR Diff 命令已变更** | `pr +diff` 已移除(与 `file` 命令冗余)。取 PR 代码差异用 `pr +versions --id <pr>` 拿 `version_id`,再 `pr +version-diff --id <pr> --version-id <vid>`(diff 在 `files[].sections[].lines[]`,`type` 2=新增/3=删除/4=hunk 头) | `pr +version-diff` 替代原 `pr +diff`;`--file` 过滤不稳,建议整份取后客户端筛 | +| **Issue 打标签需用 Raw API** | `issue +update --label <id>` 不可用(CLI 发单数 `issue_tag_id`,被忽略);`issue +batch-update --label a,b,c` 是**集合式**(整组标签打到每个 Issue,非按位置对应) | 打标签用 Raw API `PATCH /:owner/:repo/issues/:n --body '{"issue_tag_ids":[<id>],"subject":"<原>","description":"<原>"}'`;`label +list` 返回 `data.issue_tags[]`,`issue +view` 标签字段为 `tags` | +| **PR 行内评论锚定失效** | `pr +create-comment --path --line --body` 返回 `ok` 但 `line_code=null`,评论未真正绑定到行(仅文件级) | 评审意见优先放 `pr +review --status <common\|approved\|rejected> --content`;单条补充用 `pr +comment`(不绑行) | ## 文件操作 API