GitHub Reader
Read a GitHub repository's current state and produce a structured Markdown summary. Live data comes from gh CLI — no MCP needed. A user-supplied gh JSON export is also valid when the environment cannot reach GitHub: verify its repository and capture time, use its raw total_count and collection payloads, and label the report “as of” that capture instead of presenting it as a live query.
This skill serves two purposes:
- Direct answer: respond to the user's question about the repo
- Data feed: provide structured input for downstream skills like
roadmap-genorweekly-report
Reader-Facing Writing Composition
For substantial reader-facing prose, co-load human-writing even on direct
invocation; use the same context, not a later pass. This Skill retains evidence,
facts, required structure, paths, gates, and verification. Skip code-, config-, schema-,
lockfile-, and data-only output.
Mandatory Status Shape
Full status includes a milestone progress table with percentages, separate PR
queues for pending review and merged work, and each PR number linked to its
absolute GitHub URL. Use the repository status emoji vocabulary (✅, 🟢, 🟡,
🔴, ⚪) consistently. Feed mode must also emit a
github_reader_data YAML block. Every aggregate issue/PR total must carry the
raw GitHub search total_count query evidence; if unavailable, label the total
unavailable rather than deriving or fabricating it.
Step 1 — Establish repo context
If the request names a repository and supplies a local GitHub evidence export,
read that export first. It must identify the repository, captured_at, raw search
query results, and any fetched milestone/issue/PR collections used by the
report. Do not call GitHub or invent missing collections; surface absent or
incomplete fields with the same completeness rules as a live query.
宿主存在 docs/site/standards/change-map.yaml 时,项目探索先按 pm-agent 唯一维护源 consumption-contract.md(the active installed idea-to-spec skill's _internal/_shared/consumption-contract.md)执行“任务落点 → change-map 反查 → 精准读取 → 关键判断回代码验证”;不存在时静默沿用当前代码探索。
gh repo view --json nameWithOwner,url,defaultBranchRef,description
If the user specified a repo (e.g. owner/repo), use that. Otherwise use the current directory's remote. Capture OWNER, REPO, and REPO_URL for link formatting.
Step 2 — Determine query scope
Read the user's request to decide what to fetch. Three modes:
| Mode | When | What to fetch |
|---|---|---|
| Full status | "项目状态" / "health check" / no specific focus | Milestones + open issues summary + PR queue |
| Focused query | Specific question ("哪些 PR 等 review", "milestone X 进度") | Only the relevant data |
| Feed mode | Called by another skill needing raw data | Full status, output structured for downstream use |
Default to Full status if the intent is ambiguous.
Step 3 — Fetch data
Run only what the scope requires. Commands below are the full toolkit — use selectively.
Step 3a — Count collections before fetching
Full status / Feed mode 下,在获取各计算集合前,必须先通过 search API 取得精确总数。先计算近 14 天窗口的 {DATE},再执行:
gh api search/issues -X GET -f q='repo:{OWNER}/{REPO} is:issue is:open' --jq '{total_count, incomplete_results}'
gh api search/issues -X GET -f q='repo:{OWNER}/{REPO} is:pr is:open' --jq '{total_count, incomplete_results}'
gh api search/issues -X GET -f q='repo:{OWNER}/{REPO} is:pr is:merged merged:>{DATE}' --jq '{total_count, incomplete_results}'
gh api search/issues -X GET -f q='repo:{OWNER}/{REPO} is:issue is:closed closed:>{DATE}' --jq '{total_count, incomplete_results}'
Focused query 可按需只获取相关集合的 total_count。
[强制规则] 数据完整性声明:
- 健康摘要与汇总数字一律以 Step 3a 的
total_count为准,不得用获取集合长度冒充总数- 任一 search 查询返回
incomplete_results: true时,对应集合的总数必须标注「GitHub 标记结果不完整(incomplete_results),总数为参考值」,不得呈现为精确总数;健康摘要中相关数字带同样限定- 任一集合的获取数小于
total_count时,必须在该集合小节和健康摘要中显式声明:⚠️ 数据截断:已获取 {fetched}/{total} 条,分类统计基于已获取部分- 禁止在未声明截断的情况下,把部分集合的分类统计或健康信号呈现为完整状态
- 展示限行仅控制报告展示数量(例如待 Review 表格最多 10 行并附汇总行);计算集合限行控制用于分类和健康信号的获取集合(上限 1000)。两者互不影响
- Milestones 集合必须通过
--paginate获取完整集合;若分页获取失败或集合不完整,必须在 Milestones 小节和健康摘要中声明数据不完整,不得呈现为完整状态
Milestones
gh api repos/{OWNER}/{REPO}/milestones \
--paginate \
--jq '.[] | {title, state, open_issues, closed_issues, due_on, html_url}' \
-X GET -f state=open
Open issues (grouped by milestone)
gh issue list \
--json number,title,state,labels,milestone,assignees,createdAt,updatedAt \
--state open --limit 1000
上述 --limit 1000 是计算集合限行;open issue 分类与健康信号基于该获取集合计算。
Recently closed issues (last 14 days)
gh issue list \
--json number,title,closedAt,milestone \
--state closed --limit 1000 \
--search "closed:>$(date -d '14 days ago' +%Y-%m-%d 2>/dev/null || date -v-14d +%Y-%m-%d)"
上述 --limit 1000 是计算集合限行;近期 closed issue 分类与健康信号基于该获取集合计算。
PR queue
gh pr list \
--json number,title,state,author,reviewDecision,createdAt,labels,isDraft \
--state open --limit 1000
上述 --limit 1000 是计算集合限行;open PR 分类与健康信号基于该获取集合计算。
[强制规则] PR 分类处理流程:
- 先按
author.login过滤 bot(含[bot]后缀)→ 归入 Bot 区域- 再按
isDraft过滤草稿 → 归入草稿区域- 剩余按
reviewDecision分:CHANGES_REQUESTED→ 需作者跟进;其余 → 待 Review- 待 Review 表格必须包含
labels列(取 label name,逗号分隔;无标签写-)- Full-status 模式下待 Review 表格最多 10 行,超出写汇总行
Recently merged PRs (last 14 days)
gh pr list \
--json number,title,mergedAt,author \
--state merged --limit 1000 \
--search "merged:>$(date -d '14 days ago' +%Y-%m-%d 2>/dev/null || date -v-14d +%Y-%m-%d)"
上述 --limit 1000 是计算集合限行;近期 merged PR 分类与健康信号基于该获取集合计算。
Step 4 — Compute health signals
各信号基于 Step 3 获取的计算集合;总数类数字来自 Step 3a 的 total_count。
From the fetched data, derive:
- Milestone completion % =
closed_issues / (open_issues + closed_issues) * 100 - Overdue milestones = milestones with
due_onin the past andopen_issues > 0 - Stale issues = open issues not updated in > 30 days
- Unassigned open issues = issues with empty
assignees - PRs waiting review = open PRs where
reviewDecisionisREVIEW_REQUIREDor null, and not draft - Draft PRs = open PRs where
isDraftis true
Step 5 — Format the output
Use this structure. Omit sections that have no relevant data.
## 项目状态:{OWNER}/{REPO} — {TODAY}
### Milestones
| Milestone | 进度 | 截止日期 | 状态 |
|-----------|------|---------|------|
| [v2.0]({URL}) | 12/20 (60%) | 2024-04-01 | 🟡 进行中 |
| [v1.5]({URL}) | 8/8 (100%) | 2024-03-01 | ✅ 完成 |
> 状态图例:✅ 完成 / 🟢 顺利 / 🟡 进行中 / 🔴 逾期 / ⚪ 无截止日期
### Open Issues ({N} 个)
**按 Milestone 分组:**
- **v2.0**({N} 个):[#{N} 标题]({URL})、...
- **无 Milestone**({N} 个):[#{N} 标题]({URL})、...
**需关注:**
- 🙋 无 assignee:{N} 个
- 😴 30 天未更新:{N} 个
### PR 队列
**待 Review — 人工贡献({N} 个,按等待时间排序):**
| # | 标题 | 作者 | 等待 | 标签 |
|---|------|------|------|------|
| [#{N}]({URL}) | 标题 | @author | {N} 天 | external, needs-triage |
> **[强制规则] Full-status 模式下,此表格最多显示 10 条**。超出部分只写一行汇总:"还有 {N} 个待 review PR 未列出,最老的是 #{X}({Y} 天)"。Focused 模式不受此限制,显示全部。
**Bot/自动化 PR({N} 个,可批量处理):**
- Dependabot: {N} 个,Renovate: {N} 个
> **[强制规则] Bot PR 必须从"待 Review"表格中剥离。** 判断标准:author 为 `dependabot[bot]`、`renovate[bot]`、`github-actions[bot]`、`stainless-app[bot]`、`copilot-swe-agent[bot]` 或任何 `[bot]` 后缀的 author。这些 PR 只在此 Bot 区域统计,不出现在上方人工 PR 表格中。
**草稿({N} 个):**
- [#{N} 标题]({URL}) — @{author},{N} 天
**需作者跟进(Changes Requested,{N} 个):**
- [#{N} 标题]({URL}) — @{author}
**近 14 天已合并({N} 个):**
- [#{N} 标题]({URL})
### 健康摘要
- 共 {N} 个 open issue,{N} 个 open PR
- {N} 个 milestone 进行中,{N} 个逾期
- 近 14 天:合并 {N} 个 PR,关闭 {N} 个 issue
- ⚠️ 积压风险(等待 > 90 天的人工 PR):{N} 个
Milestone 状态判断:
due_on为空 → ⚪ 无截止日期- 完成率 100% → ✅ 完成
due_on已过期且open_issues > 0→ 🔴 逾期- 完成率 ≥ 70% → 🟢 顺利
- 其他 → 🟡 进行中
Feed mode output
When called by another skill, append a --- separator and a machine-friendly YAML block after the Markdown report:
---
github_reader_data:
repo: owner/repo
fetched_at: 2024-03-20
open_issues_total: 15
open_prs_total: 8
merged_prs_14d_total: 4
closed_issues_14d_total: 3
truncated_collections: []
incomplete_totals: []
milestones:
- title: v2.0
completion_pct: 60
open: 8
closed: 12
due_on: 2024-04-01
overdue: false
prs_awaiting_review: 3
prs_draft: 1
unassigned_issues: 4
stale_issues: 2
健康数字字段(如 open_issues_total、open_prs_total、merged_prs_14d_total、closed_issues_14d_total)必须使用 Step 3a 的 total_count。任一计算集合被截断时,必须把集合名加入 truncated_collections(例如 [open_issues, open_prs]);任一 search 返回 incomplete_results: true,或 milestones 分页失败/集合不完整时,必须把对应集合名加入 incomplete_totals(例如 [open_issues, milestones]),告知下游对应总数为参考值。两个字段在无触发时均可省略。
This lets downstream skills parse state without re-fetching.
Edge cases
- No milestones: skip that section, note "暂无 milestone" in the summary
- Large repos: milestones 通过
--paginate获取完整集合;open issues、open PR 队列和近期 merged PR 的计算集合上限均为 1000,超出时优先用--milestone、--label或时间窗收窄。收窄后仍超出上限时,按 Step 3a 的数据完整性规则显式声明截断 - No GitHub auth:
gh auth statuswill fail — surface the error clearly and tell the user to rungh auth login - Focused query shortcut: if the user only asks about PRs, skip issue fetching entirely to save time