Issue Ingest
从上游仓库的 closed issue 批量沉淀 case。适合:团队想吸收某框架(vllm-ascend / vllm / mindspeed-llm…)的 issue 里的排障知识,而不想逐条手工翻 issue。
自动化边界(拉取→沉淀全自动;升格分场景):本 skill 自动完成"拉取 → 过滤 → 评估 → 沉淀草稿 → 标记已导入",产出 status: draft 的 case 草稿进 postmortems/inbox/——不进诊断上下文。升格分两种:
- 默认(人工审后转正):维护者批量审 inbox(knowledge-groom 周批)后转正——知识生效点(draft → active)是人;
- 自动化升格(owner 预授权源):本 skill 即 owner 配置的持续管道,其产出的草稿 verification 链完整(upstream-fix-merged 等外部验证)+ pre-triage 判别完成——可直接调 knowledge-groom 升格入库提 PR,不等周批(同 2026-W36 round2 全自动轮 22 case 先例;groom SKILL「触发场景区分」)。逐条人审不是自动化源的必经环节。
前置环境(不满足先处理,不跳过)
- gh CLI:
gh --version检查;未安装 → 提示用户安装(curl -fsSL https://cli.github.com/ | sh或包管理),装完重查; - gh 登录:
gh auth status检查;未登录 → 引导用户gh auth login(选 GitHub.com → HTTPS → Login with a web browser,用户浏览器完成授权)——不要替用户输入凭据,等 auth status 通过; - 其他源(GitCode 等):确认对应 CLI(如
gitcode-cli)已装已登录,本 skill 流程以 GitHub 为例,其他源换 CLI 命令即可(缓存格式保持一致:number/title/comments/closed_at/labels/state_reason)。
输入方式(按需交互:给得越全,问得越少)
/skill:issue-ingest --repo vllm-project/vllm-ascend --labels triaged [--since <ISO时间>] [--min-comments 3] [--limit 20] [--mode auto|confirm]
/skill:issue-ingest vllm-ascend # 半明确:调查后给建议
/skill:issue-ingest "我想导入些昇腾训练框架的 issue" # 不明确:引导问框架,再走半明确
| 用户给到什么 | agent 行为 |
|---|---|
完整参数(--repo --labels ...) |
直接执行(不打扰) |
| 半明确(框架名或仓库) | 查 ingest-state.json 该源有无 config → 有则复用(显示给用户,可改);无则调查 + 建议 + 确认(见步骤 0) |
| 不明确 | 引导问框架 → 走半明确路径 |
--repo:上游仓库(必填;半明确时 agent 从框架名映射,映射不了就问)--labels:issue 池(可覆盖 config / 映射表;默认按下表)--since:增量游标(从ingest-state.json的last_fetch_oldest_closed续拉,或用户指定)--min-comments:最少评论数(默认 3,有排查过程的信号)--limit:候选上限(默认 20)--mode:auto(默认,批量自动评估沉淀)|confirm(候选列表给用户过目后再评估)
源配置固化(ingest-state.json 的 sources..config)
交互中确认过的配置固化下来,同一仓库下次不再问同样的问题——与 case/先验沉淀同一哲学。
- 生命周期:首次导入某仓库 → 调查(label 体系/规模)→ 给建议 → 用户确认 → 写入
config(labels / min_comments / limit / strategy 说明);再次导入同仓库 → 读config直接执行(显示配置,用户可改);用户改参数 → 覆盖config - config 位置:
ingest-state.json→sources.<source>.config(与 processed/游标同处) - 更新:仓库 label 体系演进或策略变化 → 用户主动改参数时覆盖;无需显式清理
框架 label 映射(初始猜测;半明确路径先查 config,无 config 再调查确认)
| 框架 | 主池 | 说明 |
|---|---|---|
| vllm-ascend | triaged |
维护者确认过,信噪比最高;不够再扩 bug |
| vllm(上游) | bug |
无 triaged 体系时用 bug |
| 其他框架 | 调查后确认 | 先 gh api repos/<repo>/labels 看实际 label 体系再定,不猜 |
流程
0. 配置(仅半明确/不明确路径;有 config 或无参数冲突时跳过)
# 查实际 label 体系(零 token)
gh api repos/<repo>/labels --jq '.[].name'
# 数候选池规模(可选,按 label 逐个数)
gh api "search/issues?q=repo:<repo>+is:issue+is:closed+label:<候选label>&per_page=1" --jq '.total_count'
给用户建议(主池 label、min_comments、limit、预计候选数),用户确认或调整 → 写入 config;用户给了完整参数 → 跳过本步,直接执行(并把参数记入 config 供下次复用)。
python3 scripts/fetch_issues.py --repo <repo> --state closed --labels <labels> \
[--since <游标>] --output /tmp/issues-<repo>.json
只拉元数据(不含 body)。输出重定向文件,不进 context。
2. 硬过滤 + 启发式排序(0 token)
python3 scripts/issue_filter.py --cached /tmp/issues-<repo>.json \
--state ingest-state.json --source "github/<repo>" \
[--labels <labels>] [--min-comments 3] [--limit 20] [--report /tmp/candidates.json]
已处理编号排除(幂等)、label 池、评论数、标题规则;候选按 label 优先级(triaged>bug)/ 已解决 / 评论数排序。读候选列表。
增量缓存同样走本步统一过滤——--since 拉出的新缓存也过 issue_filter.py(标题规则/评论数/已处理排除都要应用),勿直接读增量文件跳过过滤(增量里的 [Doc]/[Feature] 等标题规则条目会被滤掉,直接读会混进评估)。
3. 评估(~1-2K token/条,只花在候选上)
对候选逐条:gh api repos/<repo>/issues/<n> 取 body + 评论(issue 的 body 多为环境信息+现象,根因和 fix 通常沉淀在评论里——至少读最后 2-3 条评论,结论常在尾部;body 只读现象段落),判断:
- 可否沉淀:症状→根因→fix 是否闭环(根因有定论、fix 有方向即可,不必等社区验证)、是否昇腾相关、是否与现有 case 重复(对照
knowledge/与postmortems/); - 评论数多的不等于可沉淀(可能多问题未定论)——以"根因是否定论 + fix 是否明确"为判据,不只看评论热度;
- fix 指向 PR 时,核对那个 PR 是否真的动了所述代码位(零 token:
gh pr view <n> --json title,files;要对齐到行就gh api repos/<repo>/pulls/<n>/files看 patch)。关单评论里的"#NNNNN fix it"不等于该 PR 就是所述修复——先例:VLLM-ASC-12957 被记成"PR #14269 加了流同步",而该 PR 实为删除batch_matmul_transpose算子,照 case 给用户的"升级到含 #14269 的版本"是空路。核对不上就写成待确认(草案fix_type: pending-investigation+ 注明"上游自述 PR 与所述修复不符"),不要记成既定修复; - 版本号认准维度:issue 里的
VLLM_VERSION是 vLLM 的版本,镜像 tag(如quay.io/ascend/vllm-ascend:glm5.2-a3)也不是 vllm-ascend 的版本号。写compat.ranges必须用 vllm-ascend 自身版本(pip show vllm-ascend级别的事实);取不到就留空或标注待补,不要拿 vLLM 版本凑——先例:VLLM-ASC-12461 的版本范围一度按现场的VLLM_VERSION=0.21.0误判; - 不可沉淀(feature/讨论/无结论)→ 跳过,但记录到
ingest-state.json的processed(--mark-imported一并标记,防反复评估)。
--mode confirm:先展示候选列表(编号/标题/评论数)给用户确认取舍,再评估。
4. 沉淀 + 同步 pre-triage(~3-5K token/条,产资产)
评估通过的 → 走 /skill:to-postmortem 逐条提炼(症状/根因/fix/命名空间建议),产出 case 草稿 + postmortem 进 postmortems/inbox/。批量时逐条执行,不合并多 issue 为一条 case。
产出时同步 pre-triage(省去提交时重复判断):用 knowledge/_index.yaml 按 symptoms/tags 定位现有 case 候选,全量读比对 root_cause 与 fix,给 new_pattern / variant_of:<case-id> / covered_by:<case-id> + 证据(简要),写入 draft 头注释(如 # pre-triage: variant_of VLLM-ASC-XXXX(同算子×同网络,增量=维护者确认升级修复))。groom 复核该标签而非重判。
5. 标记已导入(幂等闭环)
python3 scripts/issue_filter.py --state ingest-state.json \
--source "github/<repo>" --mark-imported <n1,n2,...>
把本次处理过的编号(含评估跳过与已沉淀)追加 processed——下次拉取不重导。评估跳过的不反复评估。
6. 报告落点
拉取 N 条 → 候选 M 条 → 评估通过 K 条 → 沉淀 case 草稿 K 条 → postmortems/inbox/(待审)
已标记 J 条编号(含跳过)→ ingest-state.json(幂等)
转正:维护者批量审 inbox(/skill:knowledge-groom)
7. 收尾 evolve-check(伴随演进评估,默认执行)
先落执行记录(evolve-check 读它作现场,不靠 agent 记忆):
python3 scripts/log_skill_exec.py --skill issue-ingest --products "<本轮产出 case id(submitted),...>" --reason "<一句话:拉取 N/评估 K/沉淀 M>" --source issue-ingest --tokens <估算>
沉淀完成、出最终报告前,执行一次伴随演进评估(read skills/evolve-check/SKILL.md
遵循):本轮沉淀出 ≥3 条同根因/同族 case(T1 → 归纳 reference 候选)、发现新 issue
类型/新错误码无覆盖(T5)、或拉取/评估环节有重复手动动作或流程摩擦(T3/T4)时,
agent 自动产 idea 卡并自行验证执行(ev_proposal 产卡 → golden/S2 验证 → 进攒批);
无信号则报告加一行"evolve-check:无演进信号"。这是流程默认收尾,不需要用户另说
"改进系统"——演进由数据触发,像人学习。产出与流程报告一并给出。
与既有 skill 的关系
- to-postmortem:issue 提炼复用其沉淀逻辑(本 skill 只做"外部源的预过滤与编排",不重复提炼);
- knowledge-groom:inbox 批量审、转正、索引重建在 groom 轮;
- 诊断(diagnose):沉淀的 case 转正后进入 Tier 2,下次诊断命中。
幂等与可重复
ingest-state.json:processed(已处理编号,硬排除)+last_fetch_*_closed(游标)+config(用户确认过的源配置)——重复运行不重导、不重评估、不重问配置;- 拉取无状态、过滤纯本地——管道可重复执行,结果稳定。
为什么需要专门入口
工程师不会为了"把 issue 翻一遍"写 postmortem;但上游 issue 里躺着大量已验证的排障知识(triaged = 维护者确认过)。专门的批量入口把门槛降到一条命令:拉取、过滤、评估、沉淀全自动,人只审转正。