mcpField
P
pr-gardening

pr-gardening

github.com/paperclipai测试与质量108.3k78 次安装今天更新
代码仓库

关于 pr-gardening

用于发现并跟踪近期由 Paperclip 实例创建的 Pull Request,并检查当前提交的就绪状态。该技能可协调后续准备任务并发布报告,同时保持 GitHub 只读,禁止合并、批准或关闭操作。

主要功能

  1. 01发现符合范围的 Pull Request
  2. 02检查当前提交的就绪状态
  3. 03派发并去重准备任务
  4. 04在来源 issue 中留言
  5. 05生成并发布就绪报告
  6. 06可选归档符合条件的收件箱 issue

适用场景

  1. 01检查近期由实例创建的 Pull Request
  2. 02找出检查失败或长期未更新的 PR
  3. 03协调后续准备工作
  4. 04不执行合并或批准地报告就绪情况

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/paperclipai/paperclip --skill pr-gardening

安装后在 Claude Code 中输入/pr-gardening确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

scripts/
check-readiness.mjs
find-candidates.mjs
lib.mjs
pr-gardening.test.mjs
render-report.mjs

详细介绍

PR 整理

主动整理 此 Paperclip 实例开启的拉取请求,这些请求在近期时间窗口内(默认为 14 天)被活跃的 Paperclip 问题提及。候选项发现和就绪状态检查由脚本完成,不进行 LLM 分析。整个工作流中,GitHub 访问始终为只读。

范围 — 仅处理我们的 PR

默认情况下,此工作流只整理由此实例的 GitHub 身份(gh 已认证的登录名,例如 cryppadotta)创建的拉取请求。社区贡献和 dependabot PR 会在 Stage A 中按作者登录名以机械方式排除,并记录在 droppedCommunityPullRequests 中;不得手动重新纳入。只有调用方明确传入 --authors 或 --include-community 时,才可以扩大范围。

严格限制

  • 绝不合并、批准或关闭拉取请求。
  • 绝不指示其他人员或 Agent 合并、批准或关闭拉取请求。
  • 绝不整理或评论社区 PR,也绝不对其运行 /prepare-paperclip-pr。 只有 Stage A 作者允许列表中的 PR 才可操作。
  • 绝不使用会更改状态的 gh 命令或会更改状态的 GitHub API 请求。脚本只使用 gh pr view 和只读 gh api GET 请求。
  • 草稿拉取请求仅作报告。不要对草稿发布整理评论。
  • 只对现有的源问题发表评论。绝不为每个拉取请求创建整理问题。
  • --dry-run 会禁止所有 Paperclip 状态变更,包括整理评论、准备任务和收件箱归档。任何模式下,发现和 GitHub 检查都保持只读。

输入

  • --days <N>:活动时间窗口,默认为 14。同时适用于提及问题的活动时间和 PR 自身的 updatedAt;窗口内没有活动的开放 PR 会作为过时项移除。
  • --authors <logins>:以逗号分隔的 GitHub 登录名,指定纳入范围的 PR 作者;默认使用 gh 已认证的用户。
  • --include-community:完全禁用作者筛选。仅在调用方明确请求时使用。
  • --repo <owner/repo>:GitHub 仓库,默认通过 gh repo view 检测。
  • --dry-run:发现、验证并生成报告,但不发布评论、不创建准备任务,也不归档收件箱条目。
  • --archive-inbox:GitHub 确认候选 PR 已在当前头部提交版本合并后,在 Stage D 中将源问题从负责用户的收件箱中归档。
  • --cooldown-hours <N>:重复整理的冷却时间,默认为 48。
  • --max-rounds <N>:每个 PR 的最大整理轮数,默认为 3。

使用由本次运行专属的目录保存生成文件,例如 $PAPERCLIP_RUN_SCRATCH_DIR/pr-gardening。

Stage A — 发现候选项

运行提取搜索流程。它会扫描每一页结果,规范化 PR URL,按 PR 编号去重,记录每个提及该 PR 的问题,检查问题产物以识别源问题,移除 GitHub 显示为已合并或已关闭的 PR,将作者不在允许列表中的 PR(社区贡献)移至 droppedCommunityPullRequests,并将自身 updatedAt 早于时间窗口的开放 PR 移至 droppedStalePullRequests。如果问题超过每个问题的提取匹配数上限(通常是列出数百个 PR URL 的摘要或 QA 问题),则记录到 source.truncatedIssues,并在报告中注明,而不是中止运行。

node .agents/skills/pr-gardening/scripts/find-candidates.mjs \
  --days 14 \
  --dry-run \
  --output "$RUN_DIR/candidates.json"

脚本会调用 GET /api/companies/:companyId/search/extract,并设置 kind=url、scope=all 和 updatedWithin=<N>d,然后除非 --authors 或 --include-community 覆盖设置,否则会通过 gh api user 解析作者允许列表。不要将其替换为完整的问题列表抓取或 LLM 扫描。

阶段 B — 验证当前头部提交的就绪状态

node .agents/skills/pr-gardening/scripts/check-readiness.mjs \
  --input "$RUN_DIR/candidates.json" \
  --output "$RUN_DIR/readiness.json" \
  --dry-run

对于每个候选项,脚本都会重新获取当前头部提交的 SHA 并记录:

  • 开启/草稿状态以及可合并性/冲突;
  • statusCheckRollup 检查运行和旧版状态清单;
  • 在确切头部提交上已完成的 Greptile 检查运行,仅当状态为 success 或 neutral 时才视为通过;
  • reviewDecision;
  • 落后于基分支的提交数。

判定结果为 ready、needs_gardening,或草稿对应的 report_only。任何唤醒 PR 或声称已修复 PR 后,都要重新运行此阶段。切勿将 issue 评论当作就绪证明。

后续创建 PR 任务去重

如果整理工作判定某个分支需要创建后续任务来发起单个拉取请求,请先去重,再创建任何内容。

对每个分支,一次处理一个分支,并按顺序执行以下操作:

  1. 搜索状态为 backlog、todo、in_progress、in_review 和 blocked 的未关闭 Paperclip issue,查找名称与分支完全匹配的 issue。
  2. 检查匹配 issue 的标题、描述和近期评论,确认是否已存在针对同一分支的等效未关闭“从此分支创建 PR”任务。
  3. 如果存在等效的未关闭任务,请复用该任务:添加简洁评论,说明当前 PR/头部提交/原因背景,并在整理 issue 或阻塞项列表中链接该任务。不要创建其他任务。
  4. 只有在不存在等效的未关闭任务时,才为该分支创建一个后续任务。

切勿并行批量创建后续任务。不要并发调用 POST /api/companies/:companyId/issues 来创建 create-PR 或 prepare-PR 任务。P1 的 issue 创建幂等支持可用后,每个 create-PR 后续任务的创建都必须包含 idempotencyKey: "pr-gardening:create-pr:{branch}",每个 prepare-PR 任务都必须包含 idempotencyKey: "pr-gardening:prepare-pr:{owner/repo}#{number}"。

阶段 C — 使用 /prepare-paperclip-pr 推进我们的 PR,直到就绪

在 --dry-run 模式下,以及对于 ready 或 report_only 条目,跳过此阶段。

此处每个 needs_gardening PR 都由此实例发起(阶段 A 可确保这一点),因此不要只汇报,而要主动运行 /prepare-paperclip-pr 技能,使其达到可合并状态。每次处理一个 PR:

  1. 冷却期和轮次。 从 candidates.json 中找到 originatingIssue(选择优先级:带有确切 PR URL、且工作产品类型为 pull_request 的 issue;然后是评论中提到该 PR 的 issue;最后是最近活跃的提及该 PR 的 issue)。获取其评论,并搜索以下标记:

    如果最新匹配标记距今未超过冷却期,则跳过该 PR。根据匹配标记跟踪轮次;三轮后停止,并报告 not converging; recommend close or human decision。这是建议由人工决定如何处置,并非要求关闭 PR。

  2. 去重。 搜索包含 PR 编号/分支的未关闭 Paperclip issue。如果已存在等效的未关闭 prepare-PR 任务,请复用该任务并添加简洁状态评论,而不要创建其他任务(见上文的去重部分)。

  3. 运行准备技能。 为每个 PR 创建一个专注的子任务,分配给编码 Agent(优先选择 CodexCoder),指示其针对该 PR 运行 /prepare-paperclip-pr——包括 PR URL、分支、当前头部提交 SHA,以及从 readiness.json 精确复制的机器检测 reasons[]。如果你是整理者,且已在工作树中检出该 PR 的分支,则可以直接运行 /prepare-paperclip-pr,而不是委派。无论哪种方式,准备工作都绝不能合并、批准或关闭 PR。

  4. 留下标记评论。 在源 issue 上发表评论,包含上述标记、当前头部提交 SHA、复制的 reasons[]、轮次计数器,以及准备任务的链接。使用 POST /api/issues/:issueId/comments 和 X-Paperclip-Run-Id。如果 issue 已处于终止状态,请包含 resume: true,以便评论创建一个可继续执行的后续任务。

建议的正文:


Gardening: dispatched `/prepare-paperclip-pr` for https://github.com/paperclipai/paperclip/pull/1234 via PAP-XXXX.

Current-head verification at `abc123` found:
- failing check: test
- Greptile missing at current head

Gardening round 1/3. Re-verification is required after changes; do not merge based on this comment.

阶段 D — 可选的收件箱整理

仅当调用方明确提供了 --archive-inbox 时才运行此阶段。即使同时提供了 --archive-inbox,--dry-run 也始终会禁止修改收件箱。未提供该标志时,不要归档任何内容。

阶段 D 适用于先前受监控且已转为已合并状态的候选项。在此阶段前立即重新运行阶段 B,并要求 GitHub 报告同一当前 head SHA 的 state: merged,该 SHA 必须与此次验证记录的 SHA 相同。阶段 A 的全新发现会有意排除已合并或已关闭的 PR。

对于每个符合条件的候选项,使用 POST /api/issues/:issueId/inbox-archive 和空 JSON 请求体,将其 originatingIssue 从负责用户的收件箱中归档。不要传递 userId;Paperclip API 会根据 gardener 的运行上下文解析负责用户,并强制执行该用户的收件箱 Agent 策略。GitHub 访问仍保持只读。

不要归档仅处于 ready 状态、未合并即关闭、处于草稿状态、待处理,或在未经验证或过时的 head 上已合并的 PR。用户仍在等待对相关问题进行审查、决策、批准或其他操作时,绝不要归档其来源问题。如果 Paperclip 因无法确定负责用户、收件箱管理已禁用、gardener 不在允许列表中或适用信任边界而拒绝修改,请报告拒绝情况,并继续执行,不要尝试绕过策略重试。

归档成功后,在来源问题上留下标准的园艺标记评论,注明已归档的问题和已合并的 PR:


Inbox tidy-up: archived [PAP-310](/PAP/issues/PAP-310) from the responsible user's inbox after confirming https://github.com/paperclipai/paperclip/pull/1234 merged at current head `abc123`.

This archive is audited and reversible; later issue activity may resurface the item.

使用 POST /api/issues/:issueId/comments,并在归档和评论请求中都包含 X-Paperclip-Run-Id。在 --dry-run 模式下,报告将要执行的归档操作和将要写入的标记评论,但不执行任何修改。

阶段 E — 监控直至终止

将园艺运行问题的 blockedByIssueIds 设置为阶段 C 中尚未终止的准备任务和已处理的来源问题,这样阻塞项解除后就会唤醒 gardener。定时或手动重新运行作为备用方案。

每次唤醒时,首先重新运行阶段 B。只有在机械验证到以下任一情况时,PR 才会从主动园艺处理中终止:

  • 已在当前 head 上验证为 ready;
  • 已在外部合并或关闭;
  • 已达到最大轮数,并报告为未能收敛。

不要让园艺问题被终止问题阻塞。不要轮询 Agent 或长时间运行的会话。

阶段 F — 生成并发布报告

node .agents/skills/pr-gardening/scripts/render-report.mjs \
  --input "$RUN_DIR/readiness.json" \
  --output "$RUN_DIR/gardening-report.md"

报告应说明范围(作者 + 时间窗口),并为每个未关闭的 PR 提供其作者、取自 PR 描述的一行用途摘要,以及就绪信心等级:

  • 高: 当前 head 的检查通过、无冲突、Greptile 检查干净、基准分支为最新状态、来源问题已终止。
  • 中: 其他方面均通过,但基准分支过时、审查尚未完成,或来源问题仍处于活动状态。
  • 低: 检查失败或待处理、缺少 Greptile、处于草稿/刚修复但未验证状态,或无法识别来源问题。

如果 PR 生成的用途说明为空或没有帮助,发布报告时应根据 PR 标题和 diff 摘要写一句描述。

将 candidates.json、readiness.json 和 gardening-report.md 上传到园艺问题,使用 Markdown 正文创建或更新 gardening-report 问题文档,并留下带有工件链接的摘要评论。报告是交付物;它绝不代表合并授权。

验证

运行有针对性的脚本测试:

node --test .agents/skills/pr-gardening/scripts/pr-gardening.test.mjs

对于实时试运行,使用 --dry-run 执行阶段 A、B 和 F,然后仅在指定 PR 仍处于未关闭状态时对其进行合理性检查。已合并或已关闭的示例应出现在 droppedClosedPullRequests 中,而不是就绪结果中;由社区作者提交的 PR 必须仅出现在 droppedCommunityPullRequests 中——作者不在允许列表中的候选项或报告条目都属于范围错误。如果还要测试 --archive-inbox,请确认报告说明了阶段 D 中被抑制的操作,并且没有发生 Paperclip 归档或标记评论修改。

评论

支持 Markdown