knowledge-groom
Skill5 starsChanged 11 days agoMITView on GitHub
昇腾知识库的周期性维护引擎。先同步远端知识到确定 commit,用有界子 agent 比对本地草稿与现有 case 的语义(root cause / 机制 / 修复 / 证据),由确定性脚本校验并保守聚合,更新本地草稿评估状态; 再批处理 postmortems/inbox/ 待审队列(预分诊 new/variant/covered 三分类), 结构化升格到 Tier 2、校验 references 完整性、检测值重复、汇总条目使用记录并算分、 软退休过期 case、重建生成索引与本期读数;并行检查与维护先验知识层(references/)—— 每轮检查 case 共性提炼缺口,维护词条草稿审核、引用校验、失效降级信号、引用发现建议。建议每周运行。 产出**变更摘要 + 待审项**交领域 owner 审;提交由 owner 自己来(不自动开 PR)。
In this repository15 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- askSkill
- diagnoseSkill
- doc-standardsSkill
- doctorSkill
- evolve-checkSkill
- issue-ingestSkill
- preload-panelSkill
- reference-ingestSkill
- resume-diagnosisSkill
- self-evolveSkill
- skill-reviewSkill
- to-postmortemSkill
- to-referenceSkill
The file
Files
Knowledge Groom
本地执行说明:本 skill 标记
disable-model-invocation(防 agent 自发启动批量改库)——skill 工具加载会报 "not available for model invocation",这是预期。用户明确要求 groom 时,agent 直接read本文件手动遵循流程即可,流程完整性不受影响;或用户输入/skill:knowledge-groom直接触发。
体系的演化引擎。不加控制的增长会摧毁检索效率——这个 skill 是知识库的"免疫系统 + 清道夫"。
触发
手动运行,建议每周一次;连续四周无新 postmortem 时可改双周——这是人的节奏判断,不是脚本行为(本仓没有 cadence 实现,别把它读成自动调度)。
触发场景区分:
- 人工使用场景(默认周批):人通过 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 段与先验层检查)token 降至可读摘要量级(<30K), 功能不缺失。纪律:
- 确定性环节一律跑脚本、只读输出摘要,不读全量原文:
- 引用完整性/悬挂/role:
scripts/verify_references.py --check(输出进摘要); - 索引/容量:
scripts/index_counts.py(条数与逐格容量,现算)+scripts/capacity_health.py(溢出/健康)输出进摘要; - 引用可观测性:
scripts/trace_metrics.py(R6,维护项,有变更才跑);tag 聚类:读_indextags 聚合(R8,零 token 机械); - 先验缺口:
scripts/ref_gap_index.py(R8,按 case 的title与symptoms里的可检索键聚合,输出三种动作); - 先验层规模/退化(R7):按文件数/metrics 判断,不逐文件读。
- 引用完整性/悬挂/role:
- 全量重扫默认关闭,改信号触发:
- R3(引用发现,需扫 case 正文):默认不跑——仅当本轮 新升格 case ≥5 且 owner 要求时执行 (R3 本就是可选项;防"每周全量扫 128 case 正文"常设成本);
- 汇总与算分(步骤 3.6 与 4):汇总与算分都是脚本(
trace_entry_activity.py、score_entries.py), 只读它们的输出摘要;步骤 4 是全库一次算完,不做逐条判断(公式住在脚本里,见 docs/mechanism/diagnosis-observability.md 3.4); - 先验层跳过规则:
references/本轮没有变更时,R1/R5/R5.5/R6 不跑,摘要写一句"references 无变更,跳过维护";R7 索引触发检测、R8 缺口候选、R9 夹具候选、R10 流程留出检验每轮跑;R2 走主流程第 2 步,R4 走信号表,R3 默认不跑。
- 预分诊比对不全文重读:先用
scripts/groom_snapshot.py取到确定的远端 commit,再用scripts/groom_candidates.py的有界候选工作单(默认 6 条、硬上限 8 条)把草稿交给子 agent; 子 agent 只读工作单里的草稿与候选摘录,不读全库。没有候选工作单时,才退回命中 (namespace × category) 的索引分片行knowledge/_index/<ns>__<category>.list(一行一条 case;category 未定回退<ns>.list; 不读全库总表)按 symptoms/tags 定位候选,并只读 1-2 个最高分候选全文核对。draft 头注释已有 to-postmortem/issue-ingest 产出的分诊建议 → 复核证据是否成立,不重判。 - 变更摘要 = 各脚本输出摘要 + agent 判断行;审计链在 EV 卡/PR,不靠每次重读全库。
Agent 语义比对(Groom 的强制前置,先于 intake)
目标:把"这份草稿与现有知识是什么关系"从"读本地旧索引猜"变成"对确定的远端 commit 做有界语义比对"。 确定性脚本负责取数、校验、聚合与落状态;子 agent 只负责读草稿与候选并返回结构化判断。
0. 确定同步源
配置优先:先看主检出 .local/settings.json 的 sync.remote,有就直接用它,下面的 --list-remotes 不跑。
python3 scripts/groom_snapshot.py --list-remotes它只列本机已经配置的远端名字,不判断托管平台、不预设任何地址。
- 只有一个远端:直接用它,不再问用户;快照命令省略
--remote,脚本会自动选它。 - 多个远端:把名字给用户,问“这次从哪个远端更新?”,再用
--remote <名字>;不要替用户选。 - 没有远端:问用户要用的名字和地址,由用户执行
git remote add <name> <url>;agent 不猜地址,也不写死任何平台或仓库端点。
--list-remotes 只读,不改仓库。
0.1 同步快照(失败就停,不拿旧数据往下走)
同步源与诊断读侧共用同一份配置:读主检出 .local/settings.json 的 sync 段(remote / branch)。配置在就按它同步,不再问远端;配置缺失才回到上一节走原有选源(单个远端直接用,多个才问用户)。有配置时下面的命令省略 --remote,脚本自己取配置。
个人配置的 sync.enabled 只管诊断读侧的自动检查,不影响本步:groom 是显式动作,即使关掉自动检查也要 fetch。整机离线用 deployment.yaml 的 sync.mode: "offline"。
有配置时,或没有配置且只有一个远端时:
python3 scripts/groom_snapshot.py --require-fresh没有配置且有多个远端时,用用户选定的那个:
python3 scripts/groom_snapshot.py --remote <用户选择的远端名> --require-fresh它只 git fetch + 在独立路径建 detach worktree,不 pull / 不 merge / 不 rebase,源工作区的本地改动与
未跟踪 inbox 不受影响。输出里的 remote 是实际使用的同步源,commit 是本轮所有判断的
compared_against_commit。
- 退出 2:同步或索引校验失败。停下来确认网络/权限;不要用当前检出里的旧
knowledge/继续判。 - 确实离线:在同一条命令上加
--offline。快照会标fresh: false, authoritative: false;本轮只能产出ambiguous/ 待复核,groom_record会把升格标成stale-snapshot,不得据此升格。 - 源工作区有未提交改动是正常的:快照不碰它,报告里会如实显示。
0.2 确定提 PR 目标(与同步源分开)
同步源决定读哪份知识(sync.remote / sync.branch),提 PR 目标决定草稿落到哪条分支(主检出 .local/settings.json 的 target.remote / target.base),两者不是一回事。
新鲜度按评估记录里的目标 ref 判:groom_record 会把快照用的 ref 写进评估状态文件(sidecar)的 provenance.target_ref,读侧按它解析当前 commit。配置目标与评估 ref 不一致、ref 不可用或已改写时,groom_status.py 报对应原因,不用 origin/main 静默替换。
提 PR 前确认目标已配置;没有就选一次,写进主检出的 settings:
python3 scripts/pr_status.py --set-target --remote <远端名> --base <分支名>面板的「保存目标」走同一条写入。没有配置目标时,groom_status.py 会显式打印实际使用的兜底基准;不要把它当成评估基准。
1. 生成有界候选工作单(脚本,不读全库)
python3 scripts/groom_candidates.py --snapshot <snapshot.json> --all --out <work-orders.json>每份草稿一张工作单:草稿本体 + 候选(默认 6 条,硬上限 8 条)的 root_cause / fix / 症状 / 诊断摘录。 候选不足时用同分类/全库最高分补位,池大小与省略数写在工作单里。不要把整个 knowledge/ 塞给子 agent。
2. 子 agent 比对(有界、只读、逐条覆盖)
- 有 subagent / Task 工具时:每份草稿一个子 agent;同时最多 3 个(硬上限 4)。提示词与返回 schema 见 references/subagent-prompts.md。
- 子 agent 只读工作单,不写任何 Case 文件、不升格、不合并、不删草稿。
- 必须逐条覆盖工作单里的每个候选;只评"看起来像的"会让未评的候选被静默忽略——
groom_record会直接判整份无效。 - 需要独立复核的情形:建议
duplicate/covered、置信度非high、证据轴出现unknown、 或候选之间结论冲突。每份草稿最多再起 1 个复核 agent;复核只能把结论往保守方向拉。 - 顺序回退:Harness 没有子 agent 机制时,主 agent 按同一提示逐份顺序做,返回同一 schema; 不得因为"没有子 agent"就退回按本地旧索引直接判。
3. 记录(确定性校验 + 保守聚合,子 agent 不落库)
python3 scripts/groom_record.py --snapshot <snapshot.json> --work-orders <work-orders.json> \
--results-dir <results/> --report- 结果文件:每份草稿只放一个
<draft_key>.result.json;重复评估要覆盖同名文件,不要生成<draft_key>-r2.result.json。出现第二份 primary 会整份拒绝,不会静默取第一份。 - 子 agent 返回:优先完整 JSON 或单个 ```json 围栏;第二个围栏、未闭合围栏、显式
Correction:/Actual:第二份结果、独立成行的第二份 JSON 值都会拒绝。围栏外的普通解释可容忍;解析器不会在自然语言里扫描数字、引号或true。 - 校验:候选必须来自工作单、逐条覆盖、分类/置信度枚举合法、rationale 非空;结果还必须回显并匹配
work_order_id/snapshot_commit/draft_sha256/candidate_ids。任一不满足 → 整份ambiguous+ 人工复核,不猜;绑定失败时promotion_gate标binding-mismatch。 - 聚合:只有
high置信度的duplicate/covered才成为建议;中/低置信度降为ambiguous; 两个候选同时被高置信度判重复 →ambiguous(不自动选一个);复核 agentchallenge/false_merge_risk→ambiguous。证据轴与分类自相矛盾时按证据降级。 - 人机分家:
human_decision只由groom_decide.py写;重跑 agent 不会覆盖人已确认的决定。 - 状态落在
postmortems/inbox/.groom/assessments/<key>.yaml(inbox 是 .gitignore 的本地队列, 状态文件不进 git);草稿原字节不变,永久 Case ID 不变。
4. 人审与决定(问答,不要只列命令)
先跑:
python3 scripts/groom_status.py --decision-prompt把每个未决草稿按下面这个形态给用户,等人回复编号后再执行 groom_decide.py:
### VLLM-ASC-14152
评估:variant(medium)
候选:VLLM-ASC-10122
理由:...
请选择:
1. 同意建议:variant(VLLM-ASC-10122)
2. 改判 new_pattern
3. 改判 variant(请给候选 Case ID)
4. 改判 covered(请给候选 Case ID)
5. defer
6. reject人回复后:
python3 scripts/groom_decide.py --draft-key <key> --decision <choice> \
--candidate <case-id> --by <owner> --note "<为什么>"duplicate/covered/variant必须由人确认;agent 建议不等于决定。- 不要只甩一段“下一步 1. python... 2. 升格...”的命令列表;先问清楚选项。
new_pattern且 high 置信度、无复核项、快照权威 → 可进入既有升格闸门(仍按第 1 步人审批审)。- 评估后知识前进或草稿被改 →
groom_status.py标STALE;重跑本轮,不得拿旧结论升格。评估是目标祖先且knowledge/真有前进才报「前进」;目标 ref 不可用、与当前目标不一致、目标落后或无法比较也会标STALE,原因分别写明,先修目标或基准再决定是否重跑。 - 旧批准失效但评估本身未过期(
revalidation-needed)→ 仍用--decision-prompt重新确认;只有评估过期才重跑 groom。 - 决定被记录为绑定
applies_to_commit;新评估与人决定冲突时保留人决定并标revalidation-needed。
5. PR provenance 与合入前复核
提 PR 时,把下面命令的输出作为一段 HTML 注释贴进 PR body(机器读它,不读 prose):
python3 scripts/groom_record.py --pr-marker --draft-key <key>合入前 / CI 里:
python3 scripts/groom_recheck.py --pr-body-file <pr-body.md> \
--base <目标远端>/<目标分支> --head <head>--base 省略时读主检出 .local/settings.json 的 target,与提 PR 目标一致;没有配置目标时仍退回 origin/main 并说明。
groom_recheck.py 是确定性检查,不需要问用户;直接跑,失败时按原因重跑 groom、重做批准或补 marker。
PR 开完后的本地台账写点:每份草稿开完 PR 后用 python3 scripts/pr_status.py --root . --set --draft <key> --platform <platform> --repo <owner/repo> --number <n> --url <url> --remote <remote> 写进共享 inbox 的 .groom/pr-state.json;不要手编 JSON。查合入状态用 --check,没有适配器时用 --mark 手动确认。PR 被关闭、这次沉淀要撤回时,撤销脚本会清掉这条记录;单独清理用 python3 scripts/pr_status.py --root . --forget --draft <key>(只允许 closed)。
assessed_commit必须真实存在且是 base 的祖先;评估后相关knowledge/变了 → 过期,重跑 groom。- marker 还必须带
schema: groom-pr/v2、assessment_id、assessed_content_sha256以及人的human_decision_assessment_id/human_decision_content_sha256。缺字段、枚举非法、批准与评估/内容不匹配 → 直接拒绝;reject/defer/covered不授权新增或修改 Case。 - 每个被提交或修改的 Case 都要有自己的 marker;marker 的
assessed_content_sha256必须等于提交 Case 的规范化内容指纹(root cause / fix / symptoms / diagnosis 等),否则content-mismatch。 - PR 新增 case 与 base 前进期间新增 case 有共同字面量 →
possible-duplicate-after-merge,要求人复核。 这是提示,不是语义判重;它拦的是"看都没看"。 - 缺 marker 默认 warning,加
--enforce时变 error;human_decision: pending、reject、defer不授权内容,始终 error。 - 升格时 final Case ID 与草稿建议 id 不同,
groom_record.py --pr-marker --submitted-case-id <final-id>把最终 id 写进 marker;不要事后手改。
6. 合入后收尾清理:复核通过后,只删这份 PR 覆盖到的产物
marker 已进 PR body、本轮记录与决定都落好、PR 已合入之后,再跑(默认执行,不向人确认):
MERGE=$(gh pr view <n> --json mergeCommit --jq .mergeCommit.oid) # GitHub
python3 scripts/groom_cleanup.py --pr-body-file <pr-body.md> --post-merge \
--base "$(git rev-parse "$MERGE^1")" --head "$MERGE"<merge> 是合入提交,base 取它的第一个父提交(git rev-parse <merge>^1)。不要用
baseRefOid:它是 PR 头更新时的 base 分支头,合并队列前进后可能已经变过。合入后
无法再对旧 base 重跑 groom,--post-merge 跳过过期判定,marker、内容绑定与索引检查仍照跑。
由 agent 决定跑不跑,判据就是脚本自己会核的三条:复核无 error、marker 与本地评估绑定一致、快照没有别的 sidecar 引用。想先看计划加 --dry-run(只看不删)。
它做的事:按 PR body 里的 marker 取 draft,先核对 marker 与本地评估是不是同一次评估(assessment_id、内容哈希、人决定三项都要对上,旧 PR 正文删不掉重评后的新记录);对得上的 sidecar 在 log_lock 内直接删除(不留回收区;锁文件是互斥原语、不随 sidecar 删);快照只在「没有任何 sidecar 再引用这个 commit」时才删,读不出评估就视为引用未知、不删快照。非终态决定(pending / defer / reject)与 approval_stale: true 一律保留。每次清理追加一行单行 JSON 到 .groom/cleanup-log.jsonl(含评估 id、内容哈希与实际结果)。
- 前置:marker 必须已经在 PR body 里,PR 已经合入。sidecar 被删后 marker 是唯一凭证;还没合入就跑 close / cleanup,PR 被拒时人的决定与评估证据都回不来。
groom_close_draft.py会读 PR 台账,PR 没合入(state 不是 merged,含 open / unknown / closed)时拒绝执行;确实要提前收尾时加--allow-open-pr。 - body 里只放终态 marker:
defer/reject的 marker 会让groom_recheck整轮判红(decision-does-not-authorize),本轮什么都删不掉。 - 为什么按 key 删而不是删整个
.groom/:inbox 与.groom/是主检出共享的,同一克隆里可能有别的 session 正在处理别的草稿;整目录删会把它们未完成的评估一起清掉。 - 顺序:建快照 → 候选 → 比对 → 记录 → 决定 → marker → 复核 → 开 PR → 合入 → 收尾(
groom_close_draft.py回写 trace 并把草稿移出队列) → 清理(groom_cleanup.py --post-merge)。groom_record与groom_recheck --post-merge还要用快照目录,收尾要读 sidecar,所以清理不能提前。 - 执行阶段持目录级清理锁(
assessment_guard,与write_assessment共用):清理期间走write_assessment的写入会等锁;Windows 上等不到锁时写侧报错、不落盘(不再无锁写入)。 - 失败即停、退出 2,报告照出;但可能部分完成:单条失败只保留该项、继续处理其余;非预期异常折成
internal-error,报告与清理日志照写。sidecar 与快照是先删、日志最后写——日志写失败时删除已经发生且不可回滚(报告标log-write-failed)。要「零删除」的保证只有一条:复核不通过时整轮直接返回。 --dry-run只是计划:执行时某条 sidecar 删不掉(unlink 被占用)会让对应快照也保留,所以实际删的只会比计划少,不会多。- 快照的保守判据:还被别的 sidecar 引用 → 不删;最近 30 分钟内刚建、
latest.json正指向它(可能有别的 session 在用)→ 跳过;目录/JSON 对不上 → 记 skipped,不写进 deleted。 - 顺带清两类可弃中间件:
.groom/runs/下超过 1 天的工作单目录(可重生成,1 天是为了避开在途 run)、以及「对应 sidecar 已不存在且超过 7 天」的残锁。锁文件只是互斥原语,有 sidecar 的一律保留;.guard.lock不清。 - 只留
latest.json(约 2 KB,记录"上一次比的是哪个 commit");它不随清理消失。 - sidecar 的删除是有代价的:人的决定与
human_decision_history不可再生,所以cleanup-log.jsonl会原样记下by/decided_at/note/applies_to_commit与历史条数,marker 已经在 PR body 里才是安全前提。 - 单人机器上也可以直接删整个
.groom/,但那会连带删掉同克隆里别人未完成的评估。
并发边界(必须如实说,不能靠 Git 同步冒充全局唯一)
fetch+ 快照只回答"我这一版知识是不是最新的"。它看不见同一时刻另一个贡献者未提交的草稿, 也不保证合入时 main 还是这个 commit。- 因此本地 groom 判
new_pattern不等于全局唯一;合入前必须重跑groom_recheck.py, 平台侧还必须要求 base 最新(分支保护 / 合并队列)。后者是部署前提,本仓脚本不实现这一层。 - 两个 PR 同时改同一 case 的字段、或 A 先合入使 B 的评估过期:recheck 报出来,人工重跑/解冲突; 不实现自动合并、不自动改写 Case ID、不删除草稿。
- 合入后由主干 job 重建索引;没有该 job 的部署按既有纪律在 main 上重建,再复查
build_index --check。
流程(一次 groom 产出一个变更摘要)
- intake 队列处理(升格的前置):处理
postmortems/inbox/(/skill:to-postmortem//skill:issue-ingest的产出都落这里;先解析一次:python3 scripts/shared_dir.py inbox给出主检出的绝对路径——草稿是锚在主检出的共享队列,在 worktree 里用相对postmortems/inbox/会读成一个空队列):- 先读本轮评估状态:先按 0.2 确认提 PR 目标,再跑
python3 scripts/groom_status.py看 assessment / 候选 / 人决定 / 新鲜度与实际比较的目标 ref。没有本地评估状态文件(sidecar)的草稿先补跑上一节语义比对,不拿旧索引判、也不直接升格。 - stale 的草稿:先看原因是知识前进、草稿改动,还是目标缺失/不一致。目标类原因先修目标,不要直接重跑;只有评估真的过期才重跑,且不用旧结论。
- 节律:单仓集中可周批;分布式(成员本地 inbox,远程仓不存)在提交主仓时处理——产出时已做 pre-triage(见下),groom 复核确认而非重判;
- 逐条复核预分诊(agent 判断,给证据;当前不引入 embedding,论证见 docs/adr/0002——可选论证层):
new_pattern/variant_of:<case-id>/covered_by:<case-id>+ 置信度。比对对象与候选来自 sidecar 的provenance.candidates;需要复核时读候选全文核对 root_cause/fix(成本预算第 3 条:不全文重读全库)。draft 头注释已带 to-postmortem/issue-ingest 产出的分诊建议 → 一并核对证据是否成立(建议与决定分离:判断在产出时做,groom 是审核者); 先判后看(顺序纪律,改不了的自觉就别指望):复核候选前,先只读草稿与 sidecar 的evidence轴,自己写一句判断——症状签名(错误码/关键日志行/数值阈值)、根因假设、修复族方向;再打开候选全文取证(我这条假设能否被候选解释,还是只是"看起来像")。先看候选再判断,判的是像不像而不是对不对:候选一旦在眼前,语义相近就会把判断拉过去(尤其是措辞相似但根因不同的 draft)。判断行写进批审清单:先写自己的判断,再写与 sidecar / 候选的对照结论;两者不一致时以证据为准,别用"候选里有类似的"当理由; - 产出批审清单交 owner 处理(像清 PR inbox,~30 秒/条):
covered_by→ 建议关闭升格;postmortem 转正postmortems/YYYY-QN/(Tier 3 语料,不是丢弃);开 PR,合入后再跑groom_close_draft.py把草稿移出队列variant_of→ 用草稿整篇替换已有 case(先把要保留的内容合并进草稿,再评估;评估后不要再合并);若要动expected/fix_on_mismatch按高风险变更走双签new_pattern→ 结构化 + 语义校验 → 过升格闸门 → 升格knowledge/<ns>/。写 case 时删掉草稿专用的created_at(它不是 case schema 字段)。校验失败标needs-structurer-review,语义不明标needs-human-review- 升格闸门(按来源分,不是一刀切):跑
python3 scripts/verify_case_draft.py --gate <草稿路径>。- 外部来源(issue-ingest / reference-ingest 管道、无
source_session)→ 跳过闸门。这类 case 的"闭环"是维护者结论 / fix PR 已经替它确认过的(其verification档位即证明),现场没有 session 可闭环;对它们要求现场闭环等于把知识注入的主通道堵死。 - 自诊断来源(带
source_session)→ 默认须闭环(两轴,与trace-status.yaml一致):命中单看来源 trace 的feedback.outcome: resolved(fix 被应用且问题消失);无命中单没有 case 可归属,看来源 trace 的status: resolved。没闭环的不必进知识库,留在本地即可。 - 例外(未闭环但已有强外部证据):
verification∈ {upstream-fix-merged、upstream-maintainer-confirmed、upstream-official-doc、engineer-report} → 需 owner 双签方可升格。理由:新根因当天发现、修复尚未应用是知识增长的主路径,不能一律挡掉;但这档必须是外部验证,不接受investigation纯推断。 verification: investigation且未闭环 → 拦下,提示三条出路(等闭环 / 补强外部证据 / 走双签例外,草稿产出时 to-postmortem 的报告里已写闸门预判)。
- 外部来源(issue-ingest / reference-ingest 管道、无
- 转正后回写来源 trace 的沉淀状态并让草稿出队(有 PR 时等合入):转正落位、复核通过、PR 开完后就停,草稿留在 inbox;查证为 merged 后再跑
python3 scripts/groom_close_draft.py --draft-key <key> --apply(批处理收尾用--all --apply)。 没有 PR 的部署(本地沉淀)在落盘复核后直接跑。脚本会读 PR 台账:PR 没合入(state 不是 merged)时拒绝收尾, 避免把「待合入」提前写成「已升格」。 它读 sidecar 的终态决定,按落点证据回写 trace 的sedimented.state——new_pattern/variant升格 Tier 2 →{state: knowledge, caseId: <case-id>};covered(含 agent 判duplicate的精确重复) 仅 postmortem 转正 →{state: archived, caseId: <覆盖它的 case-id>}——再把草稿移进postmortems/inbox/.done/(移动不删除,移回即复活),并落一行.groom/close-log.jsonl。 证据不在就不写状态:covered 要求 postmortem 已在季度目录,new_pattern/variant 要求 case 已在knowledge/;所以先落盘再跑脚本。它必须先于第 6 步清理——清理会删掉本步要读的 sidecar;两步都等合入后再跑。 教训:曾因 groom 转正后未回写,trace 停留submitted,诊断面板"沉淀漏斗"显示 4 沉淀 → 0 转正 (数据滞后于实际入库)——零推断纪律同样约束转正侧:转正是动作,发生时必须写。 duplicate(精确重复)落成人决定covered:agent 的分类可以比人决定更具体(duplicate比covered强),但human_decision枚举里没有duplicate,两者对 Case 的授权相同(都不许新增或 修改)。groom_status.py --decision-prompt会把这种草稿的同意项直接写成covered,不要为它 编一个duplicate决定。- 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 分支)。
- 先读本轮评估状态:先按 0.2 确认提 PR 目标,再跑
引用完整性校验:扫所有 case 的
references,检查指向真实存在的文件和锚点。悬挂引用进变更摘要(自演化系统的“坏账”,不校验会静默累积)。 2.5. 先验缺口检查(每轮必跑,只读脚本):跑python3 scripts/ref_gap_index.py与python3 scripts/tag_hygiene.py。前者按 case 的title/symptoms聚合,给提炼、回链、复审三种动作;后者按 tag 聚类,标注机制、模型名、环境特性三类。两个脚本都不写文件,也不改知识库。变更摘要固定一行:提炼 X 组 / 回链 Y 组 / 复审 Z 组(
ref_gap_index可处理 ≥3 的行);本轮提炼 N 条,待 owner 定 M 组;tag 维度:机制族候选 K 组,模型名族与环境特性族合计 L 组(只计数,不进候选)。三档都没到阈值时写 0,不省略;脚本跑失败时写失败原因,不拿 0 顶替。 具体提炼什么由 owner 决定。owner 认可后,agent 在同一轮执行/skill:to-reference --ingest-cases "[id1, id2...]",候选只引用已升格的 case;判据与执行规则见「先验知识层」一节的 R8。- 值重复检测:框架 case 的
expected/fix_on_mismatch是否硬编码了common/权威记录拥有的值?是 → 标 must-fix,要求改成引用。 3.5. 现场回报结算:跑python3 scripts/settle_trace_feedback.py(游标默认落 gitignored 的共享运行时件.settle-state.json,故本步不进 git、也不该由单次诊断自己开 PR——这里是现场回报入库的唯一入口,一次覆盖当期全部事件;--state仅用于显式指定/测试)。它把 traces/ 里的feedback事件折成条目使用记录里的计数行(metrics/entry-activity.d/<周>.yaml的kind: case),不改案例文件(脚本默认 dry-run,确认 diff 后--apply)。幂等口径(按 session 逐事件记已落地):补一条新 feedback 只结算新增的那条,不重放已落地事件(重放会虚增);事件对应的 case 还没落 knowledge/ 时保持待结算并在下次重跑时补上,游标不越过它前进;事件序列被改写(非追加)时脚本拒绝结算并告警,不猜。只读复核:python3 scripts/settle_trace_feedback.py --audit交叉核对"游标说已结算"与"记录里看得见计数",报出「已结算但无效果」的条目(这是发现证据静默丢失的唯一手段,出条目就删该 session 的游标条目后重跑)。结算规则(owner 设计决策,未变):只有feedback.resolved才resolved += 1——命中(hit 事件)是系统检索行为,不代表 case 有效;可信反馈(用户确认"诊断解决了问题")才是有效性信号。not_resolved/partial→misdiagnosed += 1;来源 session 自己回报的 resolve 计self_resolved、不计入resolved。无 feedback 事件时如实跳过(反馈闭环未发生=现状,不编造)。
3.5b. S2 验证结算(validation_record 输入,与 3.5 并行):跑 python3 scripts/settle_s2_feedback.py(游标与 3.5 同一份 gitignored 共享件) 把 .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),与现场的 resolve 计数分开、不混算(resolve 只由现场回报写入使用记录;S2 另立验证记录,不被降格为无落点的旁证)。inconsistent(命中 case 但结论与 resolution 不符)是复审信号——按脚本输出候选清单走 case 复审(内容错/过时/判别力不足 → 改 case 或 rejected,走 knowledge_modification PR)。排序提示:validation_record.consistent > 0 的 case 在同等 score 下优先(内容被外部验证)。无 result 文件时如实跳过。
3.6. 汇总本机诊断记录:跑 python3 scripts/trace_entry_activity.py(默认 dry-run,确认后 --apply)。它读主检出的 traces/ 与 harness 会话日志,把本轮新增的事实折成使用记录行追加进当周源文件:
kind: case—— 被选中 / 被加载 / 被排除三种触达;kind: ref—— 先验的lookups与三态(hit / miss / skipped)、消费点(purpose);kind: tool—— 按工具的次数、p50 / p90 耗时、失败与超时数(来自会话日志,按会话 id 关联;关联不上就缺席,不补估值);- 同时写本机明细
metrics/entry-activity.local/<session_id>.yaml(含逐次工具调用与 token 账单,gitignored、锚主检出——面板读它)。
增量按「每个会话的累计计数快照」算:轨迹是追加型的,同一会话后面补上的事件要靠快照差值才能进记录(按「处理过一次就跳过」会让它们永远进不来)。无新事实时不写任何行。写完重建生成物:python3 scripts/build_entry_activity.py。
3.7. 外部对照查证(可选,只对有 upstream 锚点的 case):跑 python3 scripts/verify_upstream_outcomes.py(默认 dry-run,确认后 --apply)。它按案例的 upstream 锚点查上游 issue / PR 状态,把结局写进该 case 的 validation_record。它判断不了「现场是否解决」——那只有现场回报能给(3.5)。没有锚点的 case 如实报「不可对照」。
4. 算分(脚本,全库一次):跑 python3 scripts/score_entries.py。分数不再由 agent 判断重算、也不住在 case 文件里——它是「条目使用记录的计数」与「冷启动先验」的派生值,只落在索引生成物里(口径与公式见 docs/mechanism/diagnosis-observability.md 3.4)。你做的是读它的输出并核对,不是逐条拍分:
- 看它报的分数来源模式与「退回先验」的条数:全库还没有记录时分数全是先验值,这是事实,如实写进摘要,不当作异常;
- 看它报的表外取值(调查质量档表外的条目、来源验证档表外的条目):那些条目按兜底档算分,
investigation_quality表外的要改成high/medium/low; - 冷启动先验表(执行值住在
scripts/score_entries.py的PRIORS,与本文同源)决定没有记录时的取值:
| verification \ investigation_quality | 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 根因/修复被外部验证过,内容可默认高置信,故即使调查质量=low 也有 0.5 起点(内容对但调查表述简略,仍可信);engineer-report 同时证明现场有效,故最高。先验不等于现场校准——fix 在你环境是否适用仍要现场回报确认;没有记录时分数就停在先验值,报数时标明「内容已验证、现场待确认」。算分参数(先验等效观测 4、自证权重 0.5、衰减半衰期 12 周)是执行值,改它们要连带改 score_entries.py 与本文;理论推导见 docs/spec/design-theory.md §4.1(可选论证层)。
人工覆盖走案例的可选字段 score_override{score, reason, by}(罕见,按高风险改动走两人复核);门是 python3 scripts/score_entries.py --check-overrides。
5. 软退休:区分两种"未命中"——
- cold(从未被 quickly_check 选中)→ 不退(正确但罕见的 case 占索引成本极低,误删是静默损失)
- tried-and-failed(被选中但近 12 周未解决)且
score低 → 移入_archive/ compat版本过期 → 移入_archive/(与命中无关)- 检查
_archive/中 case 是否因新compat区间该复活(2.7 退休、2.8 恢复)
- 容量治理:被治理的量是查一次问题要读进来多少字(实读 token),不按条数——条数只作观察值记在容量表里。执行参数:评估线 8000(到线→评估能否再省:先看行宽/字段,再看平台轴切分)、硬线 20000(= 常驻指令面的量级→强制处理,先瘦身再评估拆分);两条读取路径各判一条线(类视图与 ns 兜底视图;后者 vllm-ascend 已超硬线);先验层与阶段二候选全文只量不判(先验层看检索残量:两刀切完剩多少行,随词条数线性涨)。健康指标阈值:候选溢出率 >20%、同根因重复率连续两轮上升、维护时长 >30 分钟/周。每次 groom 附容量表:各格子的条数与读入成本 + 一次诊断的四个读入分项(
python3 scripts/index_read_cost.py)+ 三项健康指标。不预拆目录:拆分是超硬线之后才评估的选项,不是到线就做的动作(拆分轴与实测代价见 docs/adr/0004 与 roadmap 的「格子容量治理」行)。越界清单与行动走python3 scripts/metrics_health.py(判据数值在metrics/gates.yaml,与本节一致)——别只看_index.yaml头注的数字:头注只列数,不判越界,也不告诉你这条闸门已经越了多久。 - 同 namespace 合并建议:相似 case 对自动提示。
- 索引维护(收尾不提交生成物):所有 KB 变更(升格 / 合并 / 退休 / 补内容)完成后,本地跑
python3 scripts/rebuild_generated.py --check预览(它重建索引、路由聚合、reference 索引、timeline 与条目使用记录并校验;会写工作区,看完git checkout -- <生成物>还原)。有合入后重建 job 的部署由主干 job 提交生成物,PR 不带;没有这个 job 的部署二选一:保留旧纪律(跑同一条命令,生成物随 PR 提交),或合入后由人在 main 上跑python3 scripts/rebuild_generated.py --sync。生成物会顺手把第 4 步算出来的分数写进索引,并在头注按模式披露这一次的分数来源(有记录 / 退回先验 / 两者并存)。门是覆盖检查(每条 case 的索引行都在、与内容对得上),另有两条内容门:全库条目 id 唯一、案例文件名与 id 一致。--check报问题 = 变更不完整、索引行被手改过,或那两条内容门不通过。要归一化(顺序/注释回到生成器口径)就重跑一次;--canonical是那个自检(不作门)。软退休的 case 移_archive/后自动从活跃索引消失。
8.5. 周界:组装本期读数(一周一次):只有周界那一次 groom 跑 python3 scripts/metrics_snapshot.py,把诊断侧 / 结构侧 / 内容流程侧拼成一份新期文件写进 metrics/timeline.d/,复核分母后随 PR 提交;metrics/timeline.yaml 由主干 job 重建(本地可跑 python3 scripts/build_timeline.py 预览,但不提交)。期文件一周一期,不跟着每次运行增长——日粒度里每次运行只有一两次诊断,比例读数全是 0/1 与 1/1,噪声盖过信号。
条目使用记录与本期读数是两个粒度:记录每次运行都追加(一行一条,3.5 / 3.6 写),期文件只在周界组装(这一步)。读端读的是生成物(metrics/entry-activity/<部署>.yaml 与 metrics/timeline.yaml),不读源。
先验知识层(references/——与 case 流程并行)
先验知识层是独立资产,维护动作与 case 平行。哪些条目每轮跑、哪些在本轮有变更时跑,见「groom 成本预算与脚本先行」第 2 条;本节写各条的动作细则。
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. 引用发现(可选建议,不强制;默认不跑,仅新升格 ≥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 检索退化(漏检增多 / 平台匹配耗时长);- 达到 → 变更摘要建议按层建索引——背景类走
scripts/build_ref_summary_index.py(生成references/_summary-index.yaml),流程类走scripts/build_procedure_index.py(生成references/_procedure-index.yaml);两层都已有生成物与--check(CI 先生成再校验),case 层build_index.py与之同构。建议不自动改生成物(生成物只由主干 job 或显式跑生成器的人写,建议与决定分离);未达到 → 不提及(目录 + grep 足够,不为不存在的规模购置基础设施)。
R8. case 共性提炼候选(case-derived reference 触发信号;每轮在流程第 2.5 步跑):两个维度各跑一个脚本,先看可检索键,再看 tag。建议与决定分离:两个维度都只给候选,是否提炼由 owner 定;owner 认可后在同一轮 groom 里由 agent 执行(不再等下一次),产出的 reference 与本轮升格随同一个 PR 提交。执行前提:case 已升格——两个脚本读当前检出的 knowledge/ 与 references/,不读 inbox 草稿;references/** 的 sources[].cases 也不得出现 postmortems/inbox/ 里的草稿 id(CI 会红)。
- 先看可检索键:跑
python3 scripts/ref_gap_index.py。它按 case 的title与symptoms里出现的错误码、0x十六进制码、环境变量名、算子名、异常类名聚合。- 键只从这两个字段抽:
diagnosis/quickly_check里的码常是判别句("报 507014 还是 507057?"),算成实例会把建议指错词条。 - 表列「可处理/组内」。「可处理」指组内还没连到该行「对应词条」的 case 数。连没连看正向边:case 的
ref_knowledge有没有指向该词条(诊断阶段二.5 读的是这条边)。反向边(词条sources[].cases引用 case)不算连上,只用来找该补的目标。 回链:有对应词条,该 case 的ref_knowledge没指向它 → 补ref_knowledge,不新建词条。对应词条有两个来源:键命中(错误码族表、缺行索引指向的词条、词条正文提到该键),或该 case 自己被某条 active 词条反向引用(那条词条就是该补的目标;组里别的 case 不会被挂上这个目标)。复审:键没有对应词条,但该 case 被非 active 词条反向引用过(draft/pending-review/deprecated)→ 先核替代词条有没有覆盖这个 case,不覆盖再提炼。诊断只读 active 词条,这类 case 现在读不到先验。提炼:键没有对应词条,该 case 也没被任何词条(active 或非 active)引用过 → 走/skill:to-reference --ingest-cases "[id1, id2...]"。表按 键 × 动作 出行,同一个 case 可以落在多行(多键,或既有键命中又被反向引用);执行前先看它在别的行是否已处理,别为一个已有对应词条的 case 再建词条。- 表只列达到阈值的行(默认可处理 ≥3 条),再按
--top截断。没进表的 case 由表后清单点名,四段都给 id:未进表的未连 case(可处理不足阈值,或所在行被截断)、没有可检索键但被 active 词条反向引用过的 case(按引用它的词条补ref_knowledge)、没有可检索键且只被非 active 词条反向引用过的 case(按 id 逐条复核;tag 维度把它们算作已收录)、没有可检索键也没有任何词条引用过的 case(覆盖缺口,tag 维度可能覆盖其中一部分)。条数以脚本输出为准,不写死在本文。
- 键只从这两个字段抽:
- 按 tag 类别过滤(
scripts/tag_hygiene.py,覆盖缺口看它):脚本标注每组为「模型名 / 环境·特性 / 机制」。只有「机制」族值得提炼——模型名族(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 仍重复建议)。这份剔除把非 active 词条的引用也算作收录;这批 case 中已连 active 词条的不会被点名,其余由上一档的回链行、复审行与表后清单点名。 - 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 的机械信号,先把候选端到人眼前。键比 tag 更接近诊断的检索入口,所以先看键。
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区间 - 条目的排序分数被
score_override手动覆盖
高风险变更要求两个 owner 签字(领域 owner + 体系维护人)。变更在 session 内随机排序审,对抗疲劳——一个 session 审 30 条变更,第 30 条得到的 scrutiny 远少于第 1 条,随机化缓解这个偏差。git 落地:变更走 PR 并打 kb/high-risk 标签,CODEOWNERS 双组路径强制对应 owner 审批(owner 未定前用 CODEOWNERS.example 占位,机制先跑;流程细节见 docs/guide/git-workflow.md——可选论证层)。
复核注意力的排序:按"对本改动声明了限制"排,不按新旧排
批审清单与变更摘要的复核顺序有一条落点:把注意力放在"对本次正在改的那一面声明了限制"的条目上,而不是放在"看起来旧"的条目上。
- "这条 last_verified 过期了"不是有效的分派信号:标出陈旧只让人知道它旧,不产生"必须去看"的动作——实测里,读起来已经定论的条目被复核的概率显著更低,而一旦它的来源被取代,基于它的判断会一致地错下去(错得还很有信心)。
- 有效的是内容型规则:本改动触及哪一面(某 case 的
compat区间 /expected阈值 /fix_on_mismatch/ 某 reference 的命令副作用或数值上限),就把对该面声明了阈值、区间或限制的条目排在前面复核——它们与改动直接冲突或直接支持,是真正会改变结论的那些。同 namespace 同 category 的条目优先于全库扫描;无此类条目的改动不进这条排序(不为排序而排序)。 - 落到哪个动作:groom 的批审清单里,把这类条目单列一段("本次改动面上声明了限制的条目"),排在常规清单之前;改
compat/expected/fix_on_mismatch时,先把这些条目核完再签字(它们是高风险变更的双签依据)。 - 强度如实标注:这是判断性规范(哪些条目"声明了限制"要人判断),不进 CI;它约束的是复核顺序,不改变任何闸门的硬度。
信号 → 动作(演化信号表)
| 信号 | 动作 |
| 单 namespace 超 30 条 | 给拆分建议(首选 category 轴) |
| 两个框架 namespace 各有条 case 指向同 root cause | 在 common/ 建权威记录,框架层加 references |
| Tier 2 未命中率 > 60% 持续两周 | 先看路由准确率(见 docs/guide/metrics.md):路由准确率低→改 triage-tree;路由准但未命中→加 case |
某 case score 高且命中频繁 | 进候选优先验证队列 |
某 case score 低仍被加载 | 标待复审;命中一次失败即转人工 |
某案例 needs-structurer-review 超 14 天 | 提醒领域 owner |
| inbox 条目停留 >2 周 | 变更摘要标红,提醒 owner(队列不是档案) |
| 某格子阶段一实读超评估线(8000 tok) | 评估能否再省:先看行宽/字段,再看要不要按平台轴切开 |
| 某格子实读超硬线(20000 tok,≈常驻指令面量级) | 强制处理:先瘦身,再评估平台轴切分(不预拆目录) |
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
遵循;先按它的第 0 步读部署声明,record-only / off 下不产卡):本轮暴露覆盖缺口(T2)、容量格子压线/健康指标恶化(T6)、reference 家族需扩
(T5)、或批审环节有重复手动动作与流程摩擦(T3/T4)时,agent 自动记录并产卡:观察交给
python3 scripts/evolve_intake.py record …(按部署声明落卡或落台账),产卡后接验证 → 进攒批;无信号则摘要加一行"evolve-check:无演进信号"。
这是流程默认收尾,不需要用户另说"改进系统"。
为什么 groom 也要挂:groom 是批量改动知识库的收尾动作(升格 / 退休 / 汇总使用记录), 一轮 groom 天然产生"同族沉淀是否达归纳阈值""格子是否压线""哪条 case 反复被复测"这类 演进信号——它不挂收尾,这批信号就只存在于 agent 记忆里(此前 groom 从未落过 exec-log、 也没有收尾协议,
docs/mechanism/run.md的"已落地含 groom"曾是纸面承诺)。
v2 职责(路线图,v1 不做)
- 结构挖掘:挖 trace 语料,报告低判别力
quickly_check、噪声 triage 分支、高验证耗时 case。让库学结构,不只 bump 分数。 - trusted auto-promotion 审计:近重复 + quickly_check 通过 + 连续 N 次兄弟命中未误诊的新 case 可 auto-promote,标
auto_promoted: true,进月度抽审。
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

