关于 pr
用于在 LobeHub 仓库中准备和创建 Pull Request 的技能,涵盖分支处理、验收检查、PR 内容及分层提交,并明确隐私与贡献来源披露规则。
主要功能
- 01检查并准备分支
- 02验收门槛与 PR 关联
- 03PR 模板和披露指引
- 04生产数据隐私规则
- 05跨层堆叠 PR 流程
适用场景
- 01为功能或修复准备评审
- 02将跨层改动拆成有序 PR
- 03编写含验收信息的 PR 描述
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ lobehub/ lobehub --skill pr安装后在 Claude Code 中输入/pr确认已加载。
附带文件agents/openai.yaml
详细介绍
创建拉取请求
分支策略
- 目标分支:
canary(开发分支,云端生产环境) main是发布分支 — 切勿直接向 main 提交 PR
步骤
1. 收集上下文(并行运行)
git branch --show-current— 当前分支名称git status --short— 未提交的更改git rev-parse --abbrev-ref @{u} 2>/dev/null— 远程跟踪状态git log --oneline origin/canary..HEAD— 尚未推送的提交gh pr list --head "$(git branch --show-current)" --json number,title,state,url— 现有 PRgit diff --stat --stat-count=20 origin/canary..HEAD— 更改摘要- 如果任务中的现有验收链接涵盖已交付行为,请复用该链接。如果需要查询,请先遵循 发布身份验证预检,然后运行
publish_lh acceptance run list --json,并按branch匹配。不要盲目取消设置 API 密钥:生产凭据可能只存在于环境中。查询不需要创建新的轮次。
2. 在默认分支上处理未提交的更改
如果当前分支是 canary(或 main)且存在未提交的更改:
- 分析差异(
git diff),了解更改内容 - 根据更改推断分支名称,格式为:
<type>/<short-description>(例如fix/i18n-cjk-spacing) - 创建并切换到新分支:
git checkout -b <branch-name> - 暂存相关文件:
git add <files>(优先使用明确的文件路径,而不是git add .) - 使用恰当的 gitmoji 消息提交
- 继续步骤 3
如果当前分支是 canary/main,但没有未提交的更改,也没有尚未推送的提交,则中止 — 没有可创建 PR 的内容。
3. 按需推送
- 没有上游分支:
git push -u origin $(git branch --show-current) - 有上游分支:
git push origin $(git branch --show-current)
4. 搜索相关 GitHub 问题
gh issue list --search "<keywords>" --state all --limit 10- 仅关联范围匹配的问题(避免关联范围过大的问题)
- 未找到匹配问题时跳过
5. 验收门槛
功能或修复必须先有已发布的验收轮次,才能创建 PR(AGENTS.md → Acceptance)。如果步骤 1 中没有找到此分支的验收轮次,请先运行 acceptance 技能,然后返回并附上其 https://app.lobehub.com/acceptance/<id> 链接。如果本次会话中已在真实产品上验证过交付内容,该技能的导入流程会直接发布已有的观察结果和产物 — 无需重新运行或重新规划。没有用户可见结果的纯重构或工具更改可以跳过验收 — 应在 PR 正文中说明,而不是省略该行。
6. 使用 gh pr create --base canary 创建 PR
- 标题:
<gitmoji> <type>(<scope>): <description> - 正文:根据 PR 模板(
.github/PULL_REQUEST_TEMPLATE.md)撰写 - 遵守该模板中的
AGENT-INSTRUCTIONSHTML 注释。保留注释,不要将其复制到可见描述中。 - 使用魔法关键词关联相关 GitHub 问题(
Fixes #123、Closes #123) - 如适用,关联 Linear 问题(
Fixes LOBE-xxx) - 在 Summary 部分的 Test 下方放置验收链接(或明确的跳过原因)。
- 创建或更新 PR 时,遵循下文 PR Template 中的来源标签、隐私和 AI 辅助规则。不要要求披露提示词,也不要因等待对方同意发布对话而阻碍常规 PR 工作流。
- 将正文写入临时文件,并使用
--body-file保留格式。
7. 将 PR 关联到验收
在 PR 创建前发布的验收轮次不包含 PR,复用该轮次是正确的,因此之后不会有其他操作将验收与 PR 关联起来。执行 gh pr create 后,立即通过生产发布环境记录关联。如果第 1 步复用了已知验收并跳过查找,publish_lh 尚未定义:现在运行发布身份验证预检来定义并验证它。
publish_lh acceptance link-pr <acceptanceId> "$(gh pr view --json url --jq .url)"
对于堆栈中的每个 PR 都要执行此操作;它们共用一个验收。如果 PR 说明不需要验收,则跳过。后续轮次只有在其 result.json 中注明 PR(pullRequest)时才会自行关联;根据分支推断出的 PR 会记录在轮次中,但绝不会建立关联。如果已安装的 CLI 不支持 link-pr,或者服务端将其拒绝并提示未知,请在回复中说明,而不是重试。
8. 在浏览器中打开
gh pr view --web
PR 模板
将 .github/PULL_REQUEST_TEMPLATE.md 作为正文结构、贡献分类、披露资格和必填字段的唯一准则。填写以下部分时,请遵循其中的 AGENT-INSTRUCTIONS:
- 摘要:每个 PR 都要填写,包括必需的贡献来源标签。即使组织成员因豁免而无需披露详情,AI 辅助完成的工作仍须标记为
AI-assisted;人工审查不会使其成为纯人工完成的工作。如果无法确定来源,请填写Unknown。 - AI 辅助:组织成员豁免仅适用于详情,不适用于来源标签。需要填写时,请根据最终差异和验证证据填写其中的六个字段,而不是依据私密对话摘要。每个 PR 填写一个部分,合并记录各次会话中使用的工具和模型;如实报告未知元数据,以及未进行的审查或检查。
提示词和对话记录默认是私密的,不属于必填字段。只有作者明确要求分享时,才审查拟分享的确切文本是否包含敏感信息,并在发布前取得确认。获准创建或更新 PR 不代表同意发布对话内容。也要检查附加的日志和截图中是否包含敏感信息。
不得包含生产数据标识符
PR 标题、正文、评论和审查回复都是公开的。绝不要在其中写入来自生产数据的标识符或详情,即使 bug 正是在生产数据中发现的:
- 记录 ID:主题(
tpc_…)、消息(msg_…)、操作(op_…)、Agent(agt_…)、文档(docs_…)、用户、设备和机器人 ID。这也包括 Agent vent ID 和内部复现报告的 ID。 - 用户详情:设备或主机名称、本地路径、文件名、引用的用户文本,以及指向用户 Agent 或主题的应用链接。
应描述证据,例如:“在一个生产环境主题中观察到”,“一位有两台桌面设备的用户(设备 A 和设备 B)”。明显的占位符(tpc_xxx、C:\Users\user)可用于示例。提交哈希、部署 ID 和代码标识符不属于生产数据。同样的规则也适用于提交消息和代码注释。
备注
- 语言:所有 PR 内容都必须使用英文
- 如果该分支已存在 PR,请告知用户,而不要创建重复 PR
堆叠式 PR(跨层功能)
上述步骤会为当前分支创建一个 PR。当单个分支的改动跨越多个层——packages/database 架构/模型 → 共享的 packages/* 库 → src/server TRPC → apps/desktop + apps/cli 调用方 → src/features UI——将其作为一个 PR 提交无法安全合并:在同一个 PR 合并之前,客户端调用的端点在主干分支上并不存在,因此任何部分合并、回滚或独立审查都会造成问题。请拆分为按顺序排列的多个 PR,从底层开始。
排序规则
只有在 PR 调用的每一层都已合入 trunk 后,该 PR 才能合并。
- 服务端契约(新增 TRPC procedure、更改返回结构、新增表/模型)先合并。
- 调用方(桌面端、CLI、UI)随后合并——它们会调用该契约。
- 用一个问题来打破僵局:“如果现在单独将它合入
canary,它能否构建并正常运行?” 如果不能,就应该放到后续 PR 中。
每个 PR 应包含哪些文件
以下情况不太直观:
- 适配契约变更的前端代码应与服务端 PR 一起提交。 如果你扩展了 TRPC 返回结构(例如
listDevices现在返回platform: string | null),消费该返回值的组件也必须在_同一个_ PR 中修改——否则服务端 PR 单独合并就会导致构建失败。契约及其仓库内的消费者应一起发布。 - 新的共享包应与其消费者一起提交,而不是放进服务端 PR,除非服务端也会导入它。只有桌面端/CLI 导入的
@lobechat/*包应随客户端 PR 一起发布。不要在较低层的 PR 中包含未使用的包。 - 工作区依赖声明(
package.json中的workspace:*、pnpm-workspace.yaml)应与导入该包的代码一起提交。
Git 操作指南——拆分已有的完整分支
起始状态:一个分支(feat/x)包含一个提交 <FULL>,其中包含所有内容,且已推送(因此远程也已有备份)。
# 1. Safety nets — make the full work unloseable before rewriting anything
git branch backup/x-full <FULL> # local ref to the full commit
git branch feat/x-clients <FULL> # the higher-layer branch starts here
# 2. Rewrite the lower-layer branch to lower-layer files only
git checkout feat/x # this becomes the SERVER PR
git reset --hard origin/canary
git checkout <FULL> -- <server/db files…> # stages just those paths
git commit -m "✨ feat(...): <server half>"
git push --force-with-lease origin feat/x # never --force; never push to canary
# 3. Build the higher-layer branch STACKED on the lower branch
git checkout feat/x-clients
git reset --hard feat/x # base = the just-rewritten server HEAD
git checkout backup/x-full -- <client/ui files…> # only the remaining paths
git commit -m "✨ feat(...): <client half>"
git push -u origin feat/x-clients
然后创建较高层的 PR,以较低层分支为基础,而不是以 trunk 为基础:
gh pr create --base feat/x --head feat/x-clients --title "…" --body "…"
--base feat/x 会让差异仅包含客户端内容(不会混入服务端文件),并从物理上杜绝客户端先于服务端合并的可能。服务端 PR 合入 canary 后,将客户端 PR 的 base 改为 canary(GitHub 通常会在基础分支合并时自动调整;请在 PR 正文中注明,以便人工确认)。
验证依赖关系确实成立
整个流程的关键在于较高层依赖较低层。请验证这一点:在堆叠式较高层分支上,对调用方进行类型检查,并确认较低层引入的符号可以解析。
cd apps/cli && bun run type-check 2>&1 | grep -iE "connect\.ts|device\.register"
# empty (re: your change) = the stacked base supplies device.register ✓
仅检查你修改过的文件——此仓库的独立类型检查会产生一些既有的环境噪声(__ELECTRON__、@/types/llm、尚未构建的 @lobechat/types),这些问题与你无关。
PR 和 Linear 事项跟踪
- 每个 PR 只关闭其所属层的问题。 服务端 PR:
Closes LOBE-<server>。客户端 PR:Closes LOBE-<pkg> / <desktop> / <cli>。不要让某个 PR 的正文声称关闭了其他层的问题。 - 两个 PR 都应标记为
Part of LOBE-<parent>。 - 创建 PR 时,将每个已关闭的子问题移至 In Review(而非 Done),并添加完成评论——参见
linear技能。
注意事项
- 绝不要推送到
canary。 使用git checkout -b feat/x origin/canary创建拆分分支时,该分支会跟踪origin/canary,因此直接运行git push会推送到 canary。务必显式指定分支名:git push origin feat/x。 - 重写较低层分支时,使用
--force-with-lease,而不是--force——如果远程分支在此期间发生变化,它会中止操作。 - 在执行
reset --hard前先备份。第 1 步中的backup/x-full加上已推送的远程分支,意味着在重写任何内容前,完整提交至少被 3 个引用指向。使用git branch --contains <FULL>验证。 - 锁文件: 这个 monorepo 不会提交根目录的
pnpm-lock.yaml,因此新增workspace:*依赖无需改动锁文件。如果仓库确实会提交锁文件,则应在拆分后于每个分支上重新生成。 - 不要过度拆分。 通常两个 PR(契约/调用方)就够了。只读取现有端点的 UI 页面可以作为后续独立 PR,但不要为了拆分而把同一层拆到多个 PR 中。