Knowledge Groom
本地执行说明:本 skill 标记
disable-model-invocation(防 agent 自发启动批量改库)——skill 工具加载会报 "not available for model invocation",这是预期。用户明确要求 groom 时,agent 直接read本文件手动遵循流程即可,流程完整性不受影响;或用户输入/skill:knowledge-groom直接触发。
体系的演化引擎。不加控制的增长会摧毁检索效率——这个 skill 是知识库的"免疫系统 + 清道夫"。
触发
手动运行,建议每周一次(连续四周无新 postmortem 则自动切双周)。
触发场景区分:
- 人工使用场景(默认周批):人通过 diagnose/to-postmortem 等沉淀的草稿——攒 inbox 到周批统一处理,人审 ~30s/条后升格提 PR(人的注意力是稀缺资源,批处理是预算分配, 原则九);
- 自动化 ingest 场景(可直接升格,不等周批):issue-ingest/S2 补 case 等自动化 链路产出的草稿——verification 链完整(upstream-fix-merged 等外部验证)+ agent 已过 语义校验 + pre-triage 判别完成,质量前提与人工场景不同,产出后可直接走本流程升格 入库提 PR(同 2026-W36 round2 全自动轮 22 case 升格先例)。前提:owner 已预授权该 自动化源(issue-ingest 链路本身即 owner 配置的持续管道,其产出视为预授权)。草稿头 注释带完整 pre-triage/verification 证据 → 复核确认而非重判。
groom 成本预算与脚本先行(token 预算纪律:确定性环节脚本先行、agent 只读摘要)
目标:单次 groom(含 inbox 段与 references 维护段)token 降至可读摘要量级(<30K), 功能不缺失。纪律:
- 确定性环节一律跑脚本、只读输出摘要,不读全量原文:
- 引用完整性/悬挂/role:
scripts/verify_references.py --check(输出进摘要); - 索引/容量:
scripts/build_index.py(头注容量)+scripts/capacity_health.py(溢出/健康)输出进摘要; - 引用可观测性:
scripts/trace_metrics.py(R6);tag 聚类:读_indextags 聚合(R8,零 token 机械); - reference 规模/退化(R7):按文件数/metrics 判断,不逐文件读。
- 引用完整性/悬挂/role:
- 全量重扫默认关闭,改信号触发:
- R3(引用发现,需扫 case 正文):默认不跑——仅当本轮 新升格 case ≥5 且 owner 要求时执行 (R3 本就是可选项;防"每周全量扫 128 case 正文"常设成本);
- confidence 重算(步骤 4):只对"结算/升格有变化的 case"重算(3.5/3.5b 输出 diff 涉及 + 新升格); 无变化跳过并说明;
- references 维护段(R1/R5/R5.5/R6):仅当 references/ 本轮有变更(新词条/修订/失效信号)才跑; 无变更 → 摘要一句"references 无变更,跳过维护段"。
- 预分诊比对不全文重读:draft 与现有 case 比对用
_index行(title/symptoms 摘要/score)定位 候选 → 只读 1-2 个最高分候选全文核对;draft 头注释已有产出时分诊建议 → 复核证据成立即可,不重判。 - 变更摘要 = 各脚本输出摘要 + agent 判断行;审计链在 EV 卡/PR,不靠每次重读全库。
流程(一次 groom 产出一个变更摘要)
- intake 队列处理(升格的前置):处理
postmortems/inbox/(/skill:to-postmortem//skill:issue-ingest的产出都落这里):- 节律:单仓集中可周批;分布式(成员本地 inbox,远程仓不存)在提交主仓时处理——产出时已做 pre-triage(见下),groom 复核确认而非重判;
- 逐条预分诊(agent 判断,给证据;当前不引入 embedding,论证见 docs/adr/0002——可选论证层):
new_pattern/variant_of:<case-id>/covered_by:<case-id>+ 置信度。比对对象:命中 namespace +common/的现有 case——用knowledge/_index.yaml行(title/symptoms 摘要/score)按 symptoms/tags 定位候选, 只读 1-2 个最高分候选全文核对 root_cause/fix(M5 成本预算 #3,不全文重读全库)。draft 头注释已带 to-postmortem/issue-ingest 产出的分诊建议 → 复核证据是否成立,不重判(建议与决定分离:判断在产出时做,groom 是审核者); - 产出批审清单交 owner 处理(像清 PR inbox,~30 秒/条):
covered_by→ 建议关闭升格;postmortem 转正postmortems/YYYY-QN/(Tier 3 语料,不是丢弃)variant_of→ 建议并入已有 case(扩 compat 区间、补 symptoms);若要动expected/fix_on_mismatch按高风险变更走双签new_pattern→ 结构化 + 语义校验 → 升格knowledge/<ns>/。校验失败标needs-structurer-review,语义不明标needs-human-review
- 转正后回写来源 trace 的沉淀状态(闭环,动作发生时写):每条被 accept 的草稿,若来源是诊断 trace(头注释记了
traces/<session_id>.yaml),转正落位后回写该 trace 的sedimented.state——new_pattern/variant_of升格 Tier 2 →{state: knowledge, caseId: <case-id>};covered_by仅 postmortem 转正 →{state: archived, caseId: <case-id>}。教训:曾因 groom 转正后未回写,trace 停留submitted,诊断面板"沉淀漏斗"显示 4 沉淀 → 0 转正(数据滞后于实际入库)——零推断纪律同样约束转正侧:转正是动作,发生时必须写。 - inbox 停留 >2 周的条目在摘要里标红(队列不是档案)
- 建议与决定分离:预分诊只排序注意力,accept / adjust / reject 由人
1.5. case 分类校验(三分类强制,废弃 other):审核/升格 case 时校验
category∈ {interrupt, precision, performance}——不存在 other。发现 other 的 case → 重新分类(按症状性质归入三分类:启动失败/崩溃/资源→interrupt,输出错误/乱码/数值异常→precision,吞吐/延迟→performance);分不进去 → 标needs-human-review,由 owner 定夺,不静默保留 other。reason:other 是分类残余,实践表明残余全部可归入三分类(曾重分类 5 条全部归入,无一条真属"其他");保留 other 会让路由层永远无法到达这些 case(triage-tree 无 other 分支)。
- 引用完整性校验:扫所有 case 的
references,检查指向真实存在的文件和锚点。悬挂引用进变更摘要(自演化系统的“坏账”,不校验会静默累积)。 - 值重复检测:框架 case 的
expected/fix_on_mismatch是否硬编码了common/权威记录拥有的值?是 → 标 must-fix,要求改成引用。 3.5. 反馈结算(confidence 输入,先于重算):跑python3 scripts/settle_trace_feedback.py --state ingest-state.json把 traces/ 里的feedback事件确定性结算进 case 的confidence.hits/misdiagnoses/last_hit(幂等——按 session+事件序列 hash 记录在 ingest-state.json,重复跑不重复累积;脚本默认 dry-run,确认 diff 后--apply)。结算规则(owner 设计决策):只有feedback.resolved才hits += 1——命中(hit 事件)是系统检索行为,不代表 case 有效;可信反馈(用户确认"诊断解决了问题")才是置信度信号。not_resolved/partial→misdiagnoses += 1。结算产出的 confidence 变更走 knowledge_modification PR(脚本本身不改 git)。无 feedback 事件时如实跳过(反馈闭环未发生=现状,不编造)。
3.5b. S2 验证结算(validation_record 输入,与 3.5 并行):跑 python3 scripts/settle_s2_feedback.py --state ingest-state.json 把 .s2-replay/*.result.yaml 的 S2 replay 结果确定性结算进 case 的 validation_record(幂等同 3.5;默认 dry-run,确认 diff 后 --apply)。语义(selfevolve-loop 重构):S2 对照的是外部 ground truth(issue resolution / 维护者 fix PR / committer 确认),结果即 feedback——只是反馈对象是"内容被外部验证"(consistent/self_consistent),与 confidence 的 S1 现场 resolve 口径分开、不混算(resolve 仍只认 S1;S2 另立验证记录,不再被降格为无落点的旁证)。inconsistent(命中 case 但结论与 resolution 不符)是复审信号——按脚本输出候选清单走 case 复审(内容错/过时/判别力不足 → 改 case 或 rejected,走 knowledge_modification PR)。排序提示:validation_record.consistent > 0 的 case 在同等 score 下优先(内容被外部验证)。无 result 文件时如实跳过。
4. 置信度重算(M5:只对有变化的 case):从 hits/misdiagnoses/last_hit 重算 confidence.score(按时间衰减)——范围 = 3.5/3.5b 结算 diff 涉及的 case + 本轮新升格 case;无变化不重算(不每周全量扫 128 case 的 hits/mis 字段)。新升格的 case 初始 score 不设 0——由 verification(来源验证强度)与 confidence(调查质量)联合决定(Beta 先验超参 $(\alpha,\beta)$ 的实例化;参数治理见 roadmap 待定池,理论推导见 docs/design-theory.md §4.1——该文档为可选论证层,本参数为执行值):
| verification \ confidence | high | medium | low |
|---|---|---|---|
upstream-fix-merged(fix PR 合入) |
0.75 | 0.6 | 0.5 |
upstream-official-doc(上游官方案例/指南文档,含验证结论) |
0.7 | 0.55 | 0.45 |
upstream-maintainer-confirmed |
0.65 | 0.5 | 0.4 |
engineer-report(现场验证) |
0.85 | 0.7 | 0.6 |
investigation / 未填 |
0.6 | 0.3 | 0.1 |
语义(分层,防误读):verification 提升的是"内容正确性"先验——fix PR 合入的 case 根因/修复被外部验证过,内容可默认高置信,故即使 confidence(调查判断)=low 也有 0.5 起点(内容对但调查表述简略,仍可信);engineer-report 同时证明现场有效,故最高。score 仍 calibrate 现场解决率——verification 只给冷启动先验,不替代 S1 现场校准(fix 在你环境是否适用仍需回报确认;无 S1 时 score 停在该先验并如实标注"内容已验证、现场待确认")。score=0 意味着新 case 永远排候选最后,对已验证的高质量 case 不合理。
5. 软退休:区分两种"未命中"——
- cold(从未被 quickly_check 选中)→ 不退(正确但罕见的 case 占索引成本极低,误删是静默损失)
- tried-and-failed(被选中但近 12 周未解决)且
score低 → 移入_archive/ compat版本过期 → 移入_archive/(与命中无关)- 检查
_archive/中 case 是否因新compat区间该复活(2.7 退休、2.8 恢复)
- 容量治理与拆分建议:cap 按 (framework × category) 格子计,执行参数:soft_cap=30(触发拆分评估)、hard_cap=60(信道物理上限,强制拆);健康指标阈值:候选溢出率 >20%、同根因重复率连续两轮上升、维护时长 >30 分钟/周。每次 groom 附容量表:各格子条数 / soft_cap、三项健康指标。任一格子超 soft_cap 即触发拆分评估(不是立即拆):查健康指标,任一恶化 → 报告内容分布 + 拆分建议(首选 category 轴深化或按 platform 轴);超 hard_cap 无论健康指标强制拆。拆分被数据预告,不被卡住才想起(论证见 docs/adr/0004——可选论证层,上述数值为执行值,参数待 metrics 复核)。越界清单与行动走
python3 scripts/metrics_health.py(判据数值在metrics/gates.yaml,与本节一致)——别只看_index.yaml头注的数字:头注只列数,不判越界,也不告诉你这条闸门已经越了多久。 - 同 namespace 合并建议:相似 case 对自动提示。
- 索引维护(收尾必做):所有 KB 变更(升格/合并/退休/改 confidence)完成后,运行
python3 scripts/build_index.py重新生成knowledge/_index.yaml并随变更摘要一起提交。--check报过期 = 变更不完整(忘了重建索引)。软退休的 case 移_archive/后自动从活跃索引消失。
reference 维护(先验知识层——与 case 流程并行;M5:本轮 references 无变更则整段跳过并在摘要说明)
先验知识层(references/)是独立资产,维护动作与 case 平行:
R1. reference 词条审核(修订 3:to-reference 产出即 active,PR review 即审核闸门——合入即生效,无常规 draft→active 翻牌流程):
- 新词条不再由 groom 翻牌:to-reference 产出
status: active随 PR 提交,深审门槛(case-derived methodology ≥3 条 case 引用)由 PR CI 强制把关——产出时不达标直接红,不会以 active 合入未达门槛词条; - groom 只处理遗留 draft(修订 3 前历史产出):逐条审 accept → 改
active/ adjust / reject / defer;停留 >2 周标红提醒(队列不是档案);无遗留则跳过; - 深审门槛:case-derived + methodology 词条需 ≥3 条 case 引用(派生计数,
verify_references.py强制)才可active——对遗留 draft 审核与 CI 一致。
R2. 引用完整性校验:case 的 ref_knowledge.ref 必须真实存在于 references/(verify_references.py 已强校验悬挂引用与非法 role——groom 把结果带进变更摘要,不重复计算)。
R3. 引用发现(可选建议,不强制;M5 默认不跑,仅新升格 ≥5 且 owner 要求时):扫描 case 的 diagnosis/fix 内容,发现隐式依赖某 active reference(如 fix 提到"HCCL_BUFFSIZE 需重启生效"而该事实是独立词条)但未填 ref_knowledge → 变更摘要建议"该 case 可补 ref_knowledge",由 owner 决定。大多数 case 是自包含闭环(quickly_check/diagnosis/fix 都在体内),不需要连——只有依赖命令副作用 / 平台硬事实 / 错误码含义等独立先验事实的少数 case 值得连;强制连接只会增加维护负担和脆弱引用。
R4. 失效与降级信号:见下方信号表新增行。
R5. 校验:改动 reference 后运行 python3 scripts/verify_references.py --check(与 build_index 并列,CI 同样强制)。
R5.5. 修订中的 reference(内容修订机制):pending-review / 遗留 draft 词条在变更摘要里列出并标注修订中/待修订,提示 owner 安排:
- 有修订 PR 在走 → 摘要注明"修订中"(status 保持降级态,diagnose 不加载);
- 无修订 PR 但已标降级 → 提示"待修订",owner 决定:小修直接改 YAML + PR,大修用
/skill:to-reference --update <ref-id>; - 修订走 PR 时按 kb/high-risk 处理(改 active 内容 = 修改已生效知识,双签)。
R6. reference 可观测性回写:跑 python3 scripts/trace_metrics.py 提取 reference 指标(hits / 引用后 resolve 率 / 平台分布),把结果带进变更摘要:
- 有数据才回写:某 ref 被引用(hits ≥1)→ 更新其
hits/last_hit字段(trace 数据积累后才有);引用后 resolve 率异常低 → 触发降级信号(见信号表); - 无数据如实显示:reference 刚建立时 trace 无
reference_lookup事件 → 如实报 0,不编造指标(诚实退化)。
R7. reference 索引触发检测(修订 2 渐进式):每次 groom 检查——
references/下文件数 >50,或 metrics 显示 reference 检索退化(漏检增多 / 平台匹配耗时长);- 达到 → 变更摘要建议生成
references/_index.yaml(build_references_index.py,与 case 层build_index.py同构)——只建议不自动生成(建议与决定分离);未达到 → 不提及(目录 + grep 足够,不为不存在的规模购置基础设施)。
R8. case 共性提炼候选(case-derived reference 触发信号):跑 python3 scripts/tag_hygiene.py(机械聚类,零 token 手扫)——同 tag 的 case ≥3 条且 ≥3 条未被 reference 收录 → 变更摘要列出该组(tag + case id),建议走 /skill:to-reference --ingest-cases "[id1, id2...]" 提炼共性(methodology / error-code 表追加)——只建议不自动提炼(建议与决定分离;同 tag 是弱信号,是否提炼由 owner 定)。
- 按 tag 类别过滤:脚本标注每组为「模型名 / 环境·特性 / 机制」。只有「机制」族值得提炼——模型名族(glm5/qwen3.5/deepseek-v4…)同模型 ≠ 同根因,提炼出来是"该模型排障清单"而非独立于事故的先验知识;环境·特性族(mtp/spec-decode/w8a8/310p/cudagraph)是"用了什么"而非"哪里坏了",且多数已被现有方法论覆盖(如
mtp归ascend-vllm-spec-decode-mtp-triage)。摘要里模型名/特性族只列一行计数,不进候选。 - 先看形态:组内根因分散(同现象不同根因)→ 适合提炼 methodology(给分流路径);根因收敛(同根因)→ 不走提炼,走 case 合并 /
variant_of(提炼只会得到一条 case 的复述)。 - 已覆盖排除由脚本做:
references/**的sources[].cases与content.*.source_cases中的 case id 自动剔除——已被 reference 收录的 case 不再重复建议(教训:glm5 组 9 条中 6 条已在glm-quantized-startup-triage,原 R8 仍重复建议)。 - tag 归一前置:脚本的
--normalize负责删除与字段重复的 tag(category/namespace 名)、合并同义/拼写变体(startup/startup-fail/startup-crash→startup-failure等,映射在脚本内)。tag 一乱 R8 就给噪声(曾实测:未归一前 tag 达 507 个,其中 ≥3 次者 70 个、聚类候选 35 组,还含precision/vllm-ascend这类零信息组);先修信号源再挑候选。
理由:共性识别靠人工不可持续(曾从 42 条 case 里人工才发现 MoE 通信算子族,且仅 4 条同 tag);tag 聚类是零 token 的机械信号,先把候选端到人眼前。
R10. 流程留出检验(methodology 的"方法"地位核验):跑 python3 scripts/flow_pool.py --flow-coverage(该脚本随 eval/flow/ 评测池引入;脚本不存在时跳过并在摘要如实标注"评测池未就绪",不臆造覆盖数据)——按每条 methodology 的 sources[].cases 把评测池样本分成「收录(该词条的来源 case,train-on-test)」与「未收录(泛化证据)」两列:
- 无未收录样本通过记录的流程,其"方法"地位未验证 → 变更摘要建议:或补判据(把案例指纹改写成可对新变体执行的阈值/分支),或摘掉 procedure 绑定(
skills/diagnose/references/procedure-gates.yaml的 selector 不再选它); - 第三轮盲测的判据:给正确流程后,收录样本 2/2 改善、未收录样本 0/5 改善且 2 次被分支判别误导——即"能对上自己收录的 case"不等于"是方法";
- 与 R8(case 共性提炼候选)配对:R8 决定"要不要提炼",R10 决定"提炼出来的算不算方法"。
- 无样本覆盖对应流程时如实显示"无数据",不编造(诚实退化)。
R9. fixture 候选语义预核(agent 预核 → 人确认,A 的语义侧):跑 python3 scripts/replay_trace.py --emit-fixtures 产出 fixture 候选(_candidate: true,期望=实际命中 case,输入=多轮 user 原文折叠,已按覆盖去重)。对每个候选做三项语义判断,填 agent_review 字段(建议与决定分离——意见供人核,不替代人):
expectation:核对命中 case 的root_cause/fix与该 trace 的证据是否一致——trustworthy(证据一致,可信)/uncertain(证据不足,需人重点核)/misdiagnosed(命中 case 与证据矛盾,建议不入 fixture,并触发误诊归因);input_sufficient:true/false——输入是否含判别信号(版本/错误码/配置),缺什么在redaction_notes旁补一句;redaction_notes:检查输入原文是否含客户敏感信息(内网 IP/路径/账号),含则标注需脱敏。 预核意见随候选交 owner,owner 确认后移除_candidate与agent_review字段入库eval/golden/;misdiagnosed的候选转误诊归因流程(trace 归因→case 错改库/执行错改 skill),不入 fixture。理由:脚本(确定性)只能保证结构正确,期望正确性与输入充分性是语义判断——agent 预核把人的核对负担从"从零核"降到"对齐意见判断",与 E1(agent 自起草候选 case)同构。
变更摘要里的高风险变更标记(强制深审,不走 30 秒快通道)
- 新建
common/权威记录 - 改
expected值 - 改
fix_on_mismatch - 改
compat区间 confidence.score被手动覆盖
高风险变更要求两个 owner 签字(领域 owner + 体系维护人)。变更在 session 内随机排序审,对抗疲劳——一个 session 审 30 条变更,第 30 条得到的 scrutiny 远少于第 1 条,随机化缓解这个偏差。git 落地:变更走 PR 并打 kb/high-risk 标签,CODEOWNERS 双组路径强制对应 owner 审批(owner 未定前用 CODEOWNERS.example 占位,机制先跑;流程细节见 docs/git-workflow.md——可选论证层)。
信号 → 动作(演化信号表)
| 信号 | 动作 |
|---|---|
| 单 namespace 超 30 条 | 给拆分建议(首选 category 轴) |
| 两个框架 namespace 各有条 case 指向同 root cause | 在 common/ 建权威记录,框架层加 references |
| Tier 2 未命中率 > 60% 持续两周 | 先看路由准确率(见 docs/metrics.md):路由准确率低→改 triage-tree;路由准但未命中→加 case |
某 case score 高且命中频繁 |
进候选优先验证队列 |
某 case score 低仍被加载 |
标待复审;命中一次失败即转人工 |
某案例 needs-structurer-review 超 14 天 |
提醒领域 owner |
| inbox 条目停留 >2 周 | 变更摘要标红,提醒 owner(队列不是档案) |
| 某 (framework×category) 格子超 soft_cap(30)且健康指标恶化 | 触发拆分评估(category 深化或 platform 轴),不等撞线 |
| 某格子超 hard_cap(60) | 强制拆分(信道物理上限) |
references/ 有遗留 draft 草稿 |
审核 R1(修订 3 前历史产出):accept 改 active / adjust / reject;case-derived methodology 未达 ≥3 引用禁止 active;新产出走 to-reference 即 active + PR 合入,不再产生新 draft |
某 reference last_verified 超 90 天未刷新 |
标 needs-review,owner 季度审 |
| case-derived methodology 被引用数 < 3(派生计数) | 不允许 active(verify_references 强制;已 active 的降 draft) |
工程师反馈某 reference 引用后诊断失败(trace outcome_after_use 恶化) |
methodology → draft + 禁用 30 天;普通 → pending-review |
某 case 的 diagnosis/fix 隐式依赖 active reference 但未填 ref_knowledge |
建议补 ref_knowledge(R3,可选——case 不强制连 reference,owner 决定) |
| 某 reference sources 链接失效(spot-check 发现) | 立即标 pending-review |
某 tool 词条全文读入 > 8K token(初始阈值,字节数/3.4)/content.commands key > 8/同文件内条目 last_verified 分化 > 90 天 |
split 建议:拆成多个用途面条目(判据见 references/_types.yaml 的 tool 段注释),人确认后执行,不自动拆 |
两个 tool 词条在 ≥5 个 trace 里同 session 共现 reference_lookup(R6 数据)且 sources[].url 同源 |
merge 建议:合并为一个用途面条目(子命令并入 content.commands),人确认 |
收尾 evolve-check(伴随演进评估,默认执行)
先落执行记录(evolve-check 读它作现场,不靠 agent 记忆):
python3 scripts/log_skill_exec.py --skill knowledge-groom --products "<升格 case id(knowledge),...>" --reason "<一句话:批审 N 条 / 升格 M 条 / 退休 K 条>" --source knowledge-groom --tokens <估算>
批审产出、出变更摘要前,执行一次伴随演进评估(read skills/evolve-check/SKILL.md
遵循):本轮暴露覆盖缺口(T2)、容量格子压线/健康指标恶化(T6)、reference 家族需扩
(T5)、或批审环节有重复手动动作与流程摩擦(T3/T4)时,agent 自动产 idea 卡并自行验证
执行(ev_proposal 产卡 → 验证 → 进攒批);无信号则摘要加一行"evolve-check:无演进信号"。
这是流程默认收尾,不需要用户另说"改进系统"。
为什么 groom 也要挂:groom 是批量改动知识库的收尾动作(升格/退休/改 confidence), 一轮 groom 天然产生"同族沉淀是否达归纳阈值""格子是否压线""哪条 case 反复被复测"这类 演进信号——它不挂收尾,这批信号就只存在于 agent 记忆里(此前 groom 从未落过 exec-log、 也没有收尾协议,
docs/evolution-run.md的"已落地含 groom"曾是纸面承诺)。
v2 职责(路线图,v1 不做)
- 结构挖掘:挖 trace 语料,报告低判别力
quickly_check、噪声 triage 分支、高验证耗时 case。让库学结构,不只 bump 分数。 - trusted auto-promotion 审计:近重复 + quickly_check 通过 + 连续 N 次兄弟命中未误诊的新 case 可 auto-promote,标
auto_promoted: true,进月度抽审。