scan-new-specs

scan-new-specs

热门

扫描 warpdotdev/warp 和 warp-server 中最近合并但尚未在 warpdotdev/docs 中有对应文档 PR 的 PRODUCT.md 规范。当找到完整规范时,自动生成完整的文档草稿 PR 并标记工程师。当规范内容过于简略无法起草时,直接通知工程师。设计为定时运行的 Oz 环境代理(例如每 2-3 天)。用于设置自动文档触发或运行手动文档覆盖检查。

146Star
1Fork
更新于 2026/7/14
SKILL.md
readonly只读
name
scan-new-specs
description

扫描 warpdotdev/warp 和 warp-server 中最近合并但尚未在 warpdotdev/docs 中有对应文档 PR 的 PRODUCT.md 规范。当找到完整规范时,自动生成完整的文档草稿 PR 并标记工程师。当规范内容过于简略无法起草时,直接通知工程师。设计为定时运行的 Oz 环境代理(例如每 2-3 天)。用于设置自动文档触发或运行手动文档覆盖检查。

scan-new-specs

扫描 warpdotdev/warpwarp-server 中最近合并但缺少对应文档草稿的产品或技术规范。对于每个缺口:

  • 如果规范完整 — 自动以环境模式运行 write-feature-docswarpdotdev/docs 中生成完整的草稿 PR,然后通知工程师审阅
  • 如果规范简略 — 直接通知工程师,要求其完善规范或手动启动文档工作流

两种情况下,都会在 #growth-docs 频道发布摘要。

配置

运行前确认以下值(或接受默认值):

设置项 默认值 描述
LOOKBACK_DAYS 3 向后扫描合并规范 PR 的天数
SLACK_CHANNEL #growth-docs 用于工程师通知和摘要的 Slack 频道
SLACK_BOT_TOKEN 来自 buzz 环境 用于通过 API 发送消息的 Slack 机器人令牌(已在 buzz Oz 环境中可用)

此技能使用 Slack API (chat.postMessage) 而非传入 webhook,支持真实的用户提及。buzz Oz 环境已包含所需的 SLACK_BOT_TOKEN,无需额外设置密钥。

如果未设置 SLACK_BOT_TOKEN,则将所有消息输出到标准输出。

步骤 1:查找最近合并的规范

列出自回溯日期以来两个仓库中合并的 PR,然后按更改文件过滤。不要使用 --search "in:files"(GitHub 不支持在 PR 搜索中按文件路径过滤),并使用在 Linux 和 macOS 上均可移植的日期命令:

# 可移植的日期计算(兼容 GNU/Linux 和 BSD/macOS)
SINCE=$(date -d "-${LOOKBACK_DAYS} days" +%Y-%m-%d 2>/dev/null \
        || date -v-${LOOKBACK_DAYS}d +%Y-%m-%d)

# 列出所有最近合并的 PR(无文件路径过滤——下一步检查文件)
gh pr list \
  --repo warpdotdev/warp \
  --state merged \
  --search "merged:>${SINCE}" \
  --json number,title,author,mergedAt,url \
  --limit 100

# 对 warp-server 重复
gh pr list \
  --repo warpdotdev/warp-server \
  --state merged \
  --search "merged:>${SINCE}" \
  --json number,title,author,mergedAt,url \
  --limit 100

对于每个返回的 PR,通过检查更改的文件来确认是否包含新的 specs/*/PRODUCT.md(这是正确的过滤步骤):

gh pr view <number> --repo warpdotdev/<repo> --json files -q '.files[].path' \
  | grep -E '^specs/.+/PRODUCT\.md$'

收集以下列表:规范 ID(specs/ 下的目录名)、规范 PR 编号和 URL、PR 作者的 GitHub 用户名、仓库(warpwarp-server)以及合并日期。

对于每个 PR 作者的 GitHub 用户名,解析其 Slack 身份:

# 从 GitHub 获取工程师的姓名和邮箱
ENG_NAME=$(gh api users/<github-username> -q '.name // .login')
ENG_EMAIL=$(gh api users/<github-username> -q '.email // empty')

# 通过邮箱查找其 Slack 用户 ID(真实提及,不仅仅是名称提及)
if [ -n "$ENG_EMAIL" ]; then
  SLACK_USER_ID=$(curl -s -H "Authorization: Bearer $SLACK_BOT_TOKEN" \
    "https://slack.com/api/users.lookupByEmail?email=${ENG_EMAIL}" \
    | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['user']['id'] if d.get('ok') else '')")
fi

# 如果查找成功,使用 <@USER_ID> 进行真实提及;否则回退到 @name
if [ -n "$SLACK_USER_ID" ]; then
  ENG_MENTION="<@${SLACK_USER_ID}>"
else
  ENG_MENTION="@${ENG_NAME} _(未找到 Slack ID — 请确认这是正确的人)_"
fi

存储 ENG_MENTIONENG_NAMEENG_GITHUB 以便在 Slack 消息中使用。

步骤 2:检查现有文档覆盖

对于每个找到的规范,检查 warpdotdev/docs 中是否有提及该规范 ID 的开放/草稿或合并的 PR。运行两个独立的查询以避免将已关闭但未合并的 PR 视为覆盖:

# 检查开放或草稿 PR
gh pr list \
  --repo warpdotdev/docs \
  --state open \
  --search "<spec-id>" \
  --json number,title,state,url \
  --limit 5

# 检查合并的 PR
gh pr list \
  --repo warpdotdev/docs \
  --state merged \
  --search "<spec-id>" \
  --json number,title,state,url \
  --limit 5

如果任一查询返回结果(存在开放、草稿或合并的 PR),则认为规范已覆盖。跳过已覆盖的规范。

如果两个查询均无结果,则认为规范未覆盖。已关闭但未合并的 PR 算作覆盖——关闭的 PR 表示工作已放弃,需要重新触发。

步骤 3:评估规范完整性

对于每个未覆盖的规范,读取 specs/<id>/PRODUCT.md 并评估其内容是否足以自动起草:

完整(继续自动起草)如果满足以下所有条件:

  • 文件至少 40 行
  • 包含 ## Behavior 部分(或等效部分),其中有编号的不变量或面向用户的步骤
  • 描述至少一个具体的用户操作(不仅仅是摘要段落)

简略(直接通知工程师)如果规范是存根——仅包含摘要部分、少于 40 行或没有行为细节。

步骤 4:根据规范完整性执行操作

路径 A:完整规范 → 自动起草

  1. 环境模式运行 write-feature-docs(详见 write-feature-docs 技能)——跳过交互式大纲确认,而是将大纲作为检查清单嵌入 PR 描述中
  2. PR 在 warpdotdev/docs 中打开,包含草稿和需要工程师验证的检查清单
  3. 请求工程师(@<github-username>)以及 @rachaelrenk@hongyi-chen 审阅
  4. SLACK_CHANNEL 发送以下 Slack 消息:
📄 *文档草稿已自动生成*

功能:*<spec-id>*(来自 `<repo>`)
规范 PR:<spec-pr-url>
<@USER_ID>(GitHub:<github-username>)

我已打开一个文档草稿 PR 供审阅:<docs-pr-url>
请检查 PR 中标有 *[UNVERIFIED]* 和 *[TODO]* 的项目——这些是唯一需要您输入的内容。

路径 B:简略规范 → 通知工程师

SLACK_CHANNEL 发送以下 Slack 消息:

📋 *新规范需要文档——细节不足,无法自动起草*

功能:*<spec-id>*(来自 `<repo>`)
规范 PR:<spec-pr-url>
<@USER_ID>(GitHub:<github-username>)

该规范的行为细节不足以让我自动生成文档。请执行以下任一操作:
• 向 `specs/<spec-id>/PRODUCT.md` 添加更多细节(包含面向用户步骤的 Behavior 部分),或者
• 在此频道中通知文档团队,我们将手动起草

如果没有未覆盖的规范,则发送:

✅ *文档覆盖扫描完成* — 所有最近合并的规范均有文档覆盖。

步骤 5:发布到 Slack

使用 Slack API 发布每条消息。使用 jq 构建 JSON 负载,以安全处理 $MESSAGE 中的换行、引号和反斜杠:

jq -n \
  --arg channel "$SLACK_CHANNEL" \
  --arg text "$MESSAGE" \
  '{channel: $channel, text: $text}' \
| curl -s -X POST https://slack.com/api/chat.postMessage \
    -H "Authorization: Bearer $SLACK_BOT_TOKEN" \
    -H 'Content-type: application/json' \
    -d @-

如果未设置 SLACK_BOT_TOKEN,则将消息输出到标准输出。

步骤 6:打印摘要

始终将运行摘要打印到标准输出:

scan-new-specs 运行摘要
  扫描的仓库:         warpdotdev/warp, warp-server
  回溯窗口:           <N> 天(自 <date> 起)
  找到的规范:         <N>
  已覆盖:             <N>
  自动起草:           <N>   (完整规范 → 已打开草稿 PR)
  已通知(简略规范): <N>   (不完整规范 → 已通知工程师)
  Slack 频道:         <channel>

调度

此技能设计为每 2-3 天作为定时 Oz 环境代理运行。Oz 代理配置的建议提示:

"运行 scan-new-specs 检查 warpdotdev/warp 和 warp-server 中新合并但未在 warpdotdev/docs 中有对应文档 PR 的 PRODUCT.md 规范。对于完整规范,自动生成文档草稿 PR 并标记工程师。对于简略规范,在 Slack 中通知工程师。在 #growth-docs 中发布摘要。使用最近 3 天作为回溯窗口。"

建议调度:每周一、周三和周五上午 9 点(太平洋时间)——足够频繁以快速捕获规范,但不会造成干扰。

去重说明

此技能在运行之间不维护持久状态。去重完全依赖于 warpdotdev/docs 中是否存在文档 PR——如果某个规范有开放或合并的 PR,则不会再次标记。这意味着除非有人为规范打开文档 PR(即使是草稿),否则规范将继续生成提醒。

边缘情况: 如果文档草稿 PR 被打开然后关闭(未合并),则规范将在下次运行时被重新标记,因为关闭的 PR 不计入覆盖。这是有意为之——关闭的 PR 表示文档工作已放弃,需要重新触发。

Slack 提及说明

此技能使用来自 buzz Oz 环境的 SLACK_BOT_TOKEN 通过 Slack API (chat.postMessage) 发送消息。这支持真实的 <@USER_ID> 提及——工程师将在检测到其规范时收到直接通知。

用户 ID 通过将工程师的 GitHub 邮箱与 Slack 的 users.lookupByEmail API 进行查找来解析。如果工程师有私密的 GitHub 邮箱,查找将失败,消息将回退为纯文本名称并附带手动验证的说明。

相关技能

  • write-feature-docs — 工程师在收到通知后运行以生成文档草稿的技能