scan-new-specs
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinesescan-new-specs
扫描新规格文档(scan-new-specs)
Scan and for recently merged product or tech specs that lack a corresponding docs draft. For each gap:
warpdotdev/warpwarp-server- If the spec is complete — automatically run in ambient mode to generate a full draft PR in
write-feature-docs, then ping the engineer to review itwarpdotdev/docs - If the spec is thin — ping the engineer directly to either flesh out the spec or kick off the docs workflow manually
In both cases, post a summary to .
#growth-docsTODO for reviewers:is a temporary channel for engineer pings. Identify a more appropriate eng-facing channel (e.g. a shared eng/docs channel,#growth-docs, or a dedicated#devchannel) once this workflow is established.#docs-requests
扫描 和 仓库中近期合并的产品或技术规格文档,检查是否缺少对应的文档草稿。针对每个缺口:
warpdotdev/warpwarp-server- 若规格文档完整 —— 在ambient模式下自动运行 ,在
write-feature-docs仓库中生成完整的草稿PR,然后通知工程师进行评审warpdotdev/docs - 若规格文档内容单薄 —— 直接通知工程师,要求其补充规格文档内容或手动启动文档工作流
无论哪种情况,都需在 频道发布总结内容。
#growth-docs评审者待办事项:是用于通知工程师的临时频道。待此工作流建立后,请确定一个更合适的面向工程师的频道(例如共享的工程/文档频道、#growth-docs或专用的#dev频道)。#docs-requests
Configuration
配置
Before running, confirm these values (or accept the defaults):
| Setting | Default | Description |
|---|---|---|
| | How many days back to scan for merged spec PRs |
| | Slack channel for engineer pings and summaries (temporary — see TODO above) |
| From | Slack bot token for posting via API (already available in the |
This skill uses the Slack API () rather than an incoming webhook, which enables real user pings. The Oz environment already has the required . No new secrets setup is needed.
chat.postMessagebuzzSLACK_BOT_TOKENIf is not set, print all messages to stdout instead.
SLACK_BOT_TOKEN运行前,请确认以下配置值(或使用默认值):
| 设置项 | 默认值 | 描述 |
|---|---|---|
| | 扫描近期合并的规格PR的回溯天数 |
| | 用于通知工程师和发布总结的Slack频道(临时频道 —— 参见上述待办事项) |
| 来自 | 用于通过API发布消息的Slack机器人令牌( |
本技能使用Slack API()而非传入webhook,支持真实的用户@提及。 Oz环境已提供所需的 ,无需配置新的密钥。
chat.postMessagebuzzSLACK_BOT_TOKEN若未设置 ,则将所有消息打印至标准输出。
SLACK_BOT_TOKENStep 1: Find recently merged specs
步骤1:查找近期合并的规格文档
List merged PRs from both repos since the lookback date, then filter by changed files. Do not use (GitHub does not support file-path filtering in PR search) and use a portable date command that works on both Linux and macOS:
--search "in:files"bash
undefined列出回溯日期以来两个仓库中合并的PR,然后按变更文件进行筛选。请勿使用 (GitHub不支持在PR搜索中进行文件路径筛选),请使用可在Linux和macOS上运行的跨平台日期命令:
--search "in:files"bash
undefinedPortable date calculation (GNU/Linux and BSD/macOS compatible)
可移植的日期计算(兼容GNU/Linux和BSD/macOS)
SINCE=$(date -d "-${LOOKBACK_DAYS} days" +%Y-%m-%d 2>/dev/null
|| date -v-${LOOKBACK_DAYS}d +%Y-%m-%d)
|| date -v-${LOOKBACK_DAYS}d +%Y-%m-%d)
SINCE=$(date -d "-${LOOKBACK_DAYS} days" +%Y-%m-%d 2>/dev/null
|| date -v-${LOOKBACK_DAYS}d +%Y-%m-%d)
|| date -v-${LOOKBACK_DAYS}d +%Y-%m-%d)
List all recently merged PRs (no file-path filter -- we check files next)
列出所有近期合并的PR(暂不进行文件路径筛选,后续步骤检查文件)
gh pr list
--repo warpdotdev/warp
--state merged
--search "merged:>${SINCE}"
--json number,title,author,mergedAt,url
--limit 100
--repo warpdotdev/warp
--state merged
--search "merged:>${SINCE}"
--json number,title,author,mergedAt,url
--limit 100
gh pr list
--repo warpdotdev/warp
--state merged
--search "merged:>${SINCE}"
--json number,title,author,mergedAt,url
--limit 100
--repo warpdotdev/warp
--state merged
--search "merged:>${SINCE}"
--json number,title,author,mergedAt,url
--limit 100
Repeat for warp-server
针对warp-server仓库重复执行上述命令
gh pr list
--repo warpdotdev/warp-server
--state merged
--search "merged:>${SINCE}"
--json number,title,author,mergedAt,url
--limit 100
--repo warpdotdev/warp-server
--state merged
--search "merged:>${SINCE}"
--json number,title,author,mergedAt,url
--limit 100
For each PR returned, check whether it actually contains a new `specs/*/PRODUCT.md` by inspecting the changed files (this is the correct filter step):
```bash
gh pr view <number> --repo warpdotdev/<repo> --json files -q '.files[].path' \
| grep -E '^specs/.+/PRODUCT\.md$'Collect the list of: spec ID (the directory name under ), spec PR number and URL, PR author GitHub username, repo ( or ), and merge date.
specs/warpwarp-serverFor each PR author's GitHub username, resolve their Slack identity:
bash
undefinedgh pr list
--repo warpdotdev/warp-server
--state merged
--search "merged:>${SINCE}"
--json number,title,author,mergedAt,url
--limit 100
--repo warpdotdev/warp-server
--state merged
--search "merged:>${SINCE}"
--json number,title,author,mergedAt,url
--limit 100
对于返回的每个PR,通过检查变更文件确认是否包含新的 `specs/*/PRODUCT.md`(这是正确的筛选步骤):
```bash
gh pr view <number> --repo warpdotdev/<repo> --json files -q '.files[].path' \
| grep -E '^specs/.+/PRODUCT\.md$'收集以下信息:规格ID( 下的目录名称)、规格PR编号和URL、PR作者的GitHub用户名、仓库( 或 )以及合并日期。
specs/warpwarp-server针对每个PR作者的GitHub用户名,解析其Slack身份:
bash
undefinedGet the engineer's name and email from GitHub
从GitHub获取工程师的姓名和邮箱
ENG_NAME=$(gh api users/<github-username> -q '.name // .login')
ENG_EMAIL=$(gh api users/<github-username> -q '.email // empty')
ENG_NAME=$(gh api users/<github-username> -q '.name // .login')
ENG_EMAIL=$(gh api users/<github-username> -q '.email // empty')
Look up their Slack user ID by email (real ping, not just a name mention)
通过邮箱查找其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
"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
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
"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
Use <@USER_ID> for a real ping if lookup succeeded; fall back to @name if not
若查找成功,则使用 <@USER_ID> 进行真实@提及;否则回退为 @name,并添加手动验证提示
if [ -n "$SLACK_USER_ID" ]; then
ENG_MENTION="<@${SLACK_USER_ID}>"
else
ENG_MENTION="@${ENG_NAME} (Slack ID not found — verify this is the right person)"
fi
Store `ENG_MENTION`, `ENG_NAME`, and `ENG_GITHUB` for use in Slack messages.if [ -n "$SLACK_USER_ID" ]; then
ENG_MENTION="<@${SLACK_USER_ID}>"
else
ENG_MENTION="@${ENG_NAME} (未找到Slack ID —— 请确认是否为正确人员)"
fi
存储 `ENG_MENTION`、`ENG_NAME` 和 `ENG_GITHUB`,用于Slack消息中。Step 2: Check for existing docs coverage
步骤2:检查现有文档覆盖情况
For each spec found, check for an open/draft or merged PR that mentions the spec ID. Run two separate queries to avoid counting closed-unmerged PRs as coverage:
warpdotdev/docsbash
undefined针对每个找到的规格文档,检查 仓库中是否存在提及该规格ID的开放/草稿或已合并PR。执行两个独立查询,避免将已关闭未合并的PR视为已覆盖:
warpdotdev/docsbash
undefinedCheck for open or draft PRs
检查开放或草稿PR
gh pr list
--repo warpdotdev/docs
--state open
--search "<spec-id>"
--json number,title,state,url
--limit 5
--repo warpdotdev/docs
--state open
--search "<spec-id>"
--json number,title,state,url
--limit 5
gh pr list
--repo warpdotdev/docs
--state open
--search "<spec-id>"
--json number,title,state,url
--limit 5
--repo warpdotdev/docs
--state open
--search "<spec-id>"
--json number,title,state,url
--limit 5
Check for merged PRs
检查已合并PR
gh pr list
--repo warpdotdev/docs
--state merged
--search "<spec-id>"
--json number,title,state,url
--limit 5
--repo warpdotdev/docs
--state merged
--search "<spec-id>"
--json number,title,state,url
--limit 5
A spec is considered **covered** if either query returns results (open, draft, or merged PR exists). Skip covered specs.
A spec is **uncovered** if neither query returns results. Closed-unmerged PRs do **not** count as coverage — a closed PR signals abandoned work that needs re-triggering.gh pr list
--repo warpdotdev/docs
--state merged
--search "<spec-id>"
--json number,title,state,url
--limit 5
--repo warpdotdev/docs
--state merged
--search "<spec-id>"
--json number,title,state,url
--limit 5
若任一查询返回结果(存在开放、草稿或已合并PR),则该规格文档被视为**已覆盖**,跳过此类规格文档。
若两个查询均无结果,则该规格文档被视为**未覆盖**。已关闭未合并的PR不视为已覆盖——关闭的PR意味着文档工作已中止,需要重新触发。Step 3: Assess spec completeness
步骤3:评估规格文档完整性
For each uncovered spec, read and assess whether it has enough content to auto-draft from:
specs/<id>/PRODUCT.mdComplete (proceed to auto-draft) if ALL of the following are true:
- File is at least 40 lines long
- Contains a section (or equivalent) with numbered invariants or user-facing steps
## Behavior - Describes at least one concrete user action (not just a summary paragraph)
Thin (ping engineer instead) if the spec is a stub — only a Summary section, fewer than 40 lines, or no behavior detail.
针对每个未覆盖的规格文档,读取 ,评估其是否有足够内容用于自动生成草稿:
specs/<id>/PRODUCT.md完整(可自动生成草稿)需同时满足以下所有条件:
- 文件长度至少为40行
- 包含 章节(或等效章节),其中包含编号的约束条件或面向用户的步骤
## Behavior - 描述至少一个具体的用户操作(而非仅摘要段落)
内容单薄(需通知工程师)指规格文档为 stub 形式——仅包含摘要章节、长度不足40行,或无行为细节。
Step 4: Act based on spec completeness
步骤4:根据规格文档完整性执行操作
Path A: Complete spec → auto-draft
路径A:完整规格文档 → 自动生成草稿
- Run in ambient mode (see
write-feature-docsskill for details) — this skips the interactive outline confirmation and instead embeds the outline as a checklist in the PR descriptionwrite-feature-docs - The PR is opened in with the draft and a checklist of items needing engineer verification
warpdotdev/docs - Request review from the engineer () and from
@<github-username>,@rachaelrenk, and@petradonka@hongyi-chen - Post this Slack message to :
SLACK_CHANNEL
📄 *Docs draft auto-generated*
Feature: *<spec-id>* (from `<repo>`)
Spec PR: <spec-pr-url>
<@USER_ID> (GitHub: <github-username>)
I’ve opened a draft docs PR for review: <docs-pr-url>
Please check the items marked *[UNVERIFIED]* and *[TODO]* in the PR — those are the only things that need your input.- 在ambient模式下运行 (详见
write-feature-docs技能)——此模式会跳过交互式大纲确认,而是将大纲作为检查清单嵌入PR描述中write-feature-docs - 在 仓库中创建包含草稿和工程师需验证事项检查清单的PR
warpdotdev/docs - 请求工程师()以及
@<github-username>、@rachaelrenk和@petradonka进行评审@hongyi-chen - 在 发布以下Slack消息:
SLACK_CHANNEL
📄 *文档草稿已自动生成*
功能:*<spec-id>*(来自 `<repo>`)
规格PR:<spec-pr-url>
<@USER_ID>(GitHub:<github-username>)
我已创建一份文档草稿PR供评审:<docs-pr-url>
请检查PR中标记为 *[UNVERIFIED]* 和 *[TODO]* 的事项——这些是仅需您参与的内容。Path B: Thin spec → ping engineer
路径B:内容单薄的规格文档 → 通知工程师
Post this Slack message to :
SLACK_CHANNEL📋 *New spec needs docs — not enough detail to auto-draft*
Feature: *<spec-id>* (from `<repo>`)
Spec PR: <spec-pr-url>
<@USER_ID> (GitHub: <github-username>)
The spec doesn’t have enough behavior detail for me to auto-generate docs yet. Please either:
• Add more detail to `specs/<spec-id>/PRODUCT.md` (a Behavior section with user-facing steps), OR
• Ping the docs team in this channel and we’ll draft it manuallyIf there are no uncovered specs, post:
✅ *Docs coverage scan complete* — all recently merged specs have docs coverage.在 发布以下Slack消息:
SLACK_CHANNEL📋 *新规格文档需要配套文档——内容不足无法自动生成草稿*
功能:*<spec-id>*(来自 `<repo>`)
规格PR:<spec-pr-url>
<@USER_ID>(GitHub:<github-username>)
该规格文档的行为细节不足,无法自动生成文档。请您选择以下操作之一:
• 为 `specs/<spec-id>/PRODUCT.md` 添加更多细节(包含面向用户步骤的Behavior章节),或
• 在本频道@文档团队,我们将手动生成文档若未发现未覆盖的规格文档,则发布:
✅ *文档覆盖范围扫描完成* —— 所有近期合并的规格文档均已覆盖。Step 5: Post to Slack
步骤5:发布至Slack
Post each message using the Slack API. Build the JSON payload with to safely handle newlines, quotes, and backslashes in :
jq$MESSAGEbash
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 @-If is not set, print the message to stdout instead.
SLACK_BOT_TOKEN使用Slack API发布每条消息。使用 构建JSON负载,以安全处理 中的换行符、引号和反斜杠:
jq$MESSAGEbash
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_TOKENStep 6: Print a summary
步骤6:打印总结
Always print a run summary to stdout:
scan-new-specs run summary
Repos scanned: warpdotdev/warp, warp-server
Lookback window: <N> days (since <date>)
Specs found: <N>
Already covered: <N>
Auto-drafted: <N> (complete spec → draft PR opened)
Pinged (thin spec): <N> (incomplete spec → engineer notified)
Slack channel: <channel>始终将运行总结打印至标准输出:
scan-new-specs 运行总结
扫描的仓库: warpdotdev/warp, warp-server
回溯窗口: <N> 天(自 <date> 起)
找到的规格文档: <N>
已覆盖的规格文档: <N>
自动生成草稿的数量: <N> (完整规格文档 → 已创建草稿PR)
已通知的单薄规格: <N> (不完整规格文档 → 已通知工程师)
Slack频道: <channel>Scheduling
调度
This skill is designed to run as a scheduled Oz ambient agent every 2–3 days. A suggested prompt for the Oz agent configuration:
"Run scan-new-specs to check warpdotdev/warp and warp-server for newly merged PRODUCT.md specs that don't have a corresponding docs PR in warpdotdev/docs. For complete specs, auto-generate a draft docs PR and tag the engineer. For thin specs, ping the engineer in Slack. Post a summary to #growth-docs. Use the last 3 days as the lookback window."
Suggested schedule: every Monday, Wednesday, and Friday at 9am PT — frequent enough to catch specs quickly, but not noisy.
本技能设计为定时运行的Oz ambient agent,每2-3天运行一次。Oz agent配置的建议提示语:
"运行scan-new-specs,检查warpdotdev/warp和warp-server仓库中新合并的PRODUCT.md规格文档是否在warpdotdev/docs仓库中有对应的文档PR。对于完整的规格文档,自动生成文档草稿PR并标记工程师;对于内容单薄的规格文档,在Slack中通知工程师。将总结发布至#growth-docs频道。使用过去3天作为回溯窗口。"
建议调度计划:每周一、周三、周五太平洋时间上午9点运行——频率足够及时发现规格文档,且不会过于频繁造成干扰。
Deduplication note
去重说明
This skill does not maintain persistent state between runs. Deduplication relies entirely on whether a docs PR exists in — if a PR is open or merged for a spec, it won't be flagged again. This means a spec will continue to generate nudges until someone opens a docs PR for it (even a draft).
warpdotdev/docsEdge case: if a docs draft PR was opened and then closed (not merged), the spec will be re-flagged on the next run since closed PRs are not counted as coverage. This is intentional — a closed PR means docs work was abandoned and needs re-triggering.
本技能在运行之间不维护持久化状态。去重完全依赖 仓库中是否存在文档PR——若某规格文档存在开放或已合并的PR,则不会再次标记。这意味着,直到有人为该规格文档创建文档PR(即使是草稿),否则会持续收到提醒。
warpdotdev/docs边缘情况:若文档草稿PR已创建但随后被关闭(未合并),则在下一次运行时该规格文档会被重新标记,因为关闭的PR不视为已覆盖。此设计是有意为之——关闭的PR意味着文档工作已中止,需要重新触发。
Slack mention note
Slack提及说明
This skill uses the Slack API () with the from the Oz environment. This supports real mentions — engineers will receive a direct notification when their spec is detected.
chat.postMessageSLACK_BOT_TOKENbuzz<@USER_ID>The user ID is resolved by looking up the engineer's GitHub email against the Slack API. If the engineer has a private GitHub email, the lookup will fail and the message will fall back to a plain-text name with a note to verify manually.
users.lookupByEmail本技能使用 Oz环境中的 通过Slack API()发送消息。支持真实的 提及——工程师在其规格文档被检测到时会收到直接通知。
buzzSLACK_BOT_TOKENchat.postMessage<@USER_ID>用户ID通过将工程师的GitHub邮箱与Slack API进行匹配解析。若工程师的GitHub邮箱为私有,则查找会失败,消息将回退为纯文本名称,并添加手动验证提示。
users.lookupByEmailRelated skills
相关技能
- — the skill engineers run to generate the docs draft after being nudged
write-feature-docs
- —— 工程师收到提醒后,用于生成文档草稿的技能
write-feature-docs