Files
reader/plans/keyword-cleanup-review-suggestions-layer-design.md
T

16 KiB
Raw Blame History

keyword-cleanup-review 建议产物补齐设计

1. 背景与目标

当前仓库已经具备 keyword cleanup review 的大部分基础设施:

  • 已有 review bundle 构建脚本 skills/keyword-cleanup-review/scripts/build_review_bundle.py
  • 已有 term stats 与 daily term index 数据源
  • 已有治理输入:configs/term_cleanup_policy.json、configs/term_watchlist.json、configs/term_change_log.json
  • 已有建议落地脚本 scripts/apply_term_suggestions.py

当前缺口是:

缺少一层“把 keyword-cleanup-bundle.json 转成正式建议产物”的实现层。

也就是说,仓库现在能生成 review bundle,也能消费 suggestions JSON,但中间缺少稳定、可复用、可落盘的 suggestions 生成器。

本轮目标是补齐最小闭环,让仓库能够从 review bundle 稳定生成两份正式建议产物:

  • outputs/term_index/review/term-cleanup-suggestions-YYYY-MM-DD.json
  • outputs/term_index/review/term-cleanup-suggestions-YYYY-MM-DD.md

并保证 JSON 与 skills/keyword-cleanup-review/references/suggestion-schema.md 对齐,且能直接衔接 scripts/apply_term_suggestions.py。

补充口径:本方案中的 JSON 是 review / apply 之间的唯一正式建议产物;bundle 与 Markdown 主要作为运行时工作文件和临时展示层,不建议与 facts/configs 一样长期沉淀。


2. 当前现状

2.1 已有输入层

build_review_bundle.py 已经把以下输入聚合成单个 bundle:

  • data/term_index/term_stats.json
  • data/term_index/daily/*.json
  • configs/term_aliases.json
  • configs/term_stopwords.json
  • configs/filter_context.personal.json
  • configs/term_cleanup_policy.json
  • configs/term_watchlist.json
  • configs/term_change_log.json

bundle 中已经包含:

  • 当前配置快照
  • 最近 N 天热点词
  • uncovered terms
  • interest review candidates
  • watch review candidates

这些信息已经足够支撑“保守的、可审查的” suggestions 生成。

2.2 已有输出消费层

scripts/apply_term_suggestions.py 已经能消费 suggestions JSON,并将接受的建议写回:

  • configs/term_aliases.json
  • configs/term_stopwords.json
  • configs/filter_context.personal.json
  • configs/term_watchlist.json
  • configs/term_change_log.json

这说明落地层已存在,缺的是中间的正式建议产物生成层。


3. 当前缺口

当前流程停在:

build_review_bundle.py -> keyword-cleanup-bundle.json

但缺少:

keyword-cleanup-bundle.json -> term-cleanup-suggestions-YYYY-MM-DD.json/.md

因此出现几个问题:

  • README / 设计文档里已经引用 suggestions 产物,但仓库内没有稳定生成脚本
  • 人工审阅与后续 apply 之间没有统一的正式交付格式
  • 同一份 bundle 无法稳定、幂等地重放为同名 suggestions 产物
  • alias / stopword / interest / watch 四类建议缺少统一出入口

4. 推荐最小闭环架构

推荐新增一层独立脚本:

  • scripts/generate_term_cleanup_suggestions.py

职责:

  • 输入:outputs/term_index/review/keyword-cleanup-bundle.json
  • 输出:
    • outputs/term_index/review/term-cleanup-suggestions-YYYY-MM-DD.json
    • outputs/term_index/review/term-cleanup-suggestions-YYYY-MM-DD.md

推荐最小数据流:

  1. build_review_bundle.py 生成 bundle
  2. generate_term_cleanup_suggestions.py 读取 bundle
  3. 脚本基于治理 hints 生成 suggestions JSON
  4. 同时渲染人类可审阅的 Markdown
  5. 审阅后可用 apply_term_suggestions.py 选择性写回配置

本轮不引入默认 LLM 路径:

  • 默认实现采用确定性规则生成
  • 如果未来需要 LLM 参与,应作为显式可选增强,而不是默认路径

5. 产物设计

5.1 JSON 产物

JSON 必须与 suggestion-schema.md 对齐,至少包含:

{
  "date": "2026-04-08",
  "based_on_days": 7,
  "alias_suggestions": [],
  "stopword_suggestions": [],
  "interest_keyword_suggestions": [
    {
      "term": "Claude Code",
      "reason": "Meets the configured interest-keyword review threshold and is not yet covered."
    }
  ],
  "watch_terms": [
    {
      "term": "A2A",
      "reason": "Falls into the configured watch-term review range and should be observed first."
    }
  ]
}

在不破坏兼容性的前提下,可以补充少量元数据字段,建议仅限:

  • source_bundle
  • policy_schema_version
  • summary

建议项字段口径:

  • alias_suggestions[]
    • from
    • to
    • reason
  • stopword_suggestions[]
    • term
    • reason
  • interest_keyword_suggestions[]
    • term
    • reason
    • 可选:total_count、days_seen、recent_count
  • watch_terms[]
    • term
    • reason
    • 可选:total_count、days_seen、recent_count

兼容性要求:

  • apply_term_suggestions.py 只依赖分类 bucket 与关键字段名
  • 因此额外证据字段只能追加,不能替换现有字段名

5.2 Markdown 产物

Markdown 推荐结构:

  1. 标题与日期
  2. 输入 bundle 与策略摘要
  3. 当前现状摘要
    • top/global 观察
    • uncovered terms 概览
    • 当前 watchlist / interest 覆盖情况
  4. 建议摘要
    • interest 建议数量
    • watch 建议数量
    • alias 建议数量
    • stopword 建议数量
  5. interest_keyword_suggestions
  6. watch_terms
  7. alias_suggestions
  8. stopword_suggestions
  9. 应用方式
    • 指向生成的 JSON
    • 给出 apply_term_suggestions.py 的调用示例

这样可以保证:

  • 人可以直接审阅
  • 机器可以直接消费同名 JSON
  • Markdown 与 JSON 始终一一对应

6. 建议生成策略

6.1 本轮主链路:interest / watch

本轮先实现最小可用主链路:

  • interest_keyword_suggestions
  • watch_terms

直接复用 bundle 中已有的:

  • governance_hints.interest_review_candidates
  • governance_hints.watch_review_candidates

原因:

  • 这些候选已经与 policy 对齐
  • 这些候选已经排除了大部分已覆盖项
  • 能直接与现有 apply 脚本形成闭环

6.2 alias / stopword 保守处理

本轮边界明确如下:

  • alias_suggestions 先保持保守,默认可为空
  • stopword_suggestions 先保持保守,默认可为空
  • 后续如果补充更强证据或人工审查规则,再逐步增强

这样可以避免在证据不足时误伤配置。

6.3 Phase 2 新方向:alias review 交给 LLM 整理

对于 alias,不再优先走程序规则匹配。 Phase 2 建议改为:

  • 程序继续负责准备 review 输入(term stats / daily / current aliases / stopwords / interest / watchlist)
  • LLM 负责整理 alias 候选
  • 默认先输出人工审阅汇报,而不是直接 apply
  • 人工确认后,再决定是否写入 term_aliases.json

这样做的原因:

  • alias 更偏语义整理,而不是简单趋势筛选
  • 与 watch / interest 相比,alias 一旦错误归并,代价更高
  • 对当前低频治理场景来说,LLM + 人工确认更轻,也比在程序里持续堆复杂规则更合适

7. 错误处理

脚本应做显式校验,并在失败时给出明确错误:

7.1 输入错误

  • bundle 文件不存在 -> 直接失败
  • bundle 不是 JSON object -> 直接失败
  • 缺少关键字段(如 days、governance_hints)-> 直接失败
  • 候选 bucket 结构错误 -> 直接失败

7.2 输出错误

  • 输出目录不存在时自动创建
  • JSON / Markdown 写入失败时直接退出非 0

7.3 数据去重与冲突

  • 同一 term 不能同时出现在 interest 与 watch 中
  • 优先级:interest_keyword_suggestions > watch_terms
  • 已在 bundle 当前配置中覆盖的 term 不重复输出

8. 幂等性

本轮要求具备基础幂等性:

  • 同一份 bundle 多次运行,默认生成同名产物
  • 同一份 bundle 多次运行,JSON 内容顺序稳定
  • Markdown 内容顺序稳定

建议做法:

  • 优先使用 bundle 的 generated_at 日期作为 suggestions 文件日期
  • term 排序按证据强度与 term 名稳定排序
  • 不在默认输出中写入“每次运行变化”的当前时间戳

这样可以让生成器作为可重放步骤存在于 review 流程中。


9. 与 apply_term_suggestions.py 的衔接

正式链路应变成:

  1. build_review_bundle.py
  2. generate_term_cleanup_suggestions.py
  3. 人工审阅 Markdown
  4. apply_term_suggestions.py --suggestions ...

衔接要求:

  • JSON bucket 名必须与 apply_term_suggestions.py 读取逻辑一致
  • date 与 based_on_days 字段保留,用于 change log 回写
  • 建议项中的 reason 直接沿用到 apply 后的 change log

这保证建议生成层不会成为孤立产物,而是正式进入 repo 治理闭环。


10. Python 3.11 依赖处理

10.1 当前现状

build_review_bundle.py 当前使用 from datetime import UTC,这要求 Python 3.11。

仓库整体 pyproject.toml 当前也声明 requires-python = ">=3.11",因此短期内使用 /usr/bin/python3.11 运行是符合仓库现状的。

10.2 短期建议

短期先在文档与验证命令中明确:

  • bundle 构建使用 /usr/bin/python3.11
  • suggestions 生成脚本也按仓库当前 3.11 基线运行

10.3 中期建议

如果后续希望把 keyword cleanup 工具链下探到 Python 3.10,可做兼容改造:

  • 把 datetime.UTC 替换为 datetime.timezone.utc
  • 重新检查相关脚本是否还有其他 3.11-only 语法或库依赖

本轮不做超范围兼容重构,只在文档中把此约束说清楚。


11. 边界与非目标

本轮明确边界:

  • 先实现 interest/watch 主链路
  • alias/stopword 先保持保守或留待后续增强
  • 不做超范围重构
  • 不把 LLM 作为默认生成路径
  • 不直接改 filter_rules.json
  • 不自动 apply 建议到配置

因此,本轮交付定义为:

  • 补齐 bundle -> suggestions 的正式实现层
  • 让 review 流程可运行、可落盘、可审阅、可应用

而不是一次性做完所有高级治理逻辑。


12. 实施建议

建议按以下小步落地:

Phase 1(已完成)

  1. 新增 scripts/generate_term_cleanup_suggestions.py
  2. 读取 bundle 并做结构校验
  3. 生成稳定排序的 interest/watch suggestions JSON
  4. Markdown 改成按需生成
  5. README / skill 文档补一条生成命令
  6. 用 /usr/bin/python3.11 完整跑通 bundle -> suggestions

完成后,keyword cleanup review 的最小正式链路变为:

review bundle -> suggestions json -> apply accepted suggestions

其中 Markdown 只是按需生成的展示层。

Phase 2(下一步)

  1. 保持程序继续准备 review 输入
  2. 引入 LLM 做 alias 候选整理
  3. 默认先生成 alias review 汇报,而不是直接 apply
  4. 由人工确认后再决定是否写入 term_aliases.json

这样 alias review 会成为一个低频治理动作,而不是主链路里的自动归一步骤。

Phase 3(下一步)

  1. 保持程序继续准备 review 输入
  2. 引入 LLM 做 stopword 候选整理
  3. 默认先生成 stopword review 汇报,而不是直接 apply
  4. 由人工确认后再决定是否写入 term_stopwords.json

这样 stopword review 会成为一个低频减噪动作,而不是主链路里的自动过滤步骤。

Phase 3 输入建议

建议给 LLM 的输入包括:

  • data/term_index/term_stats.json 中的高频词与 recent evidence
  • 最近 N 天 data/term_index/daily/*.json 的热点词上下文
  • 当前 configs/term_stopwords.json
  • 当前 configs/term_aliases.json
  • 当前 configs/filter_context.personal.json 中的 interest_keywords
  • 当前 configs/term_watchlist.json

程序层只负责把这些输入整理成紧凑 review context,不负责直接做 stopword 决策。

Phase 3 输出建议

建议 LLM 默认输出一份人工审阅汇报,而不是直接写配置:

  • 建议加入 stopword
    • 词
    • 简短理由
    • 证据(如 total_count / days_seen / recent_count)
  • 暂不建议加入 stopword
    • 词
    • 为什么虽然偏泛,但当前还不能杀
  • 需要人工判断
    • 词
    • 风险点:可能是噪声,也可能仍保留有价值信号

如需结构化输出,可额外补一份 stopword_review_candidates.json,但该文件只作为 review 输入,不直接作为自动 apply 指令。

Phase 3 审阅原则

  • 宁可少删,不乱杀
  • 优先处理过泛、低辨识度、持续污染统计的词
  • 对可能仍承载有效技术语义的词保持保守
  • 默认先汇报,确认后再执行

Phase 3 汇报模板建议

建议 stopword review 默认按以下结构汇报给用户:

  1. 建议加入 stopword
    • 词
    • 理由:为什么这个词对治理帮助低、噪声高
    • 证据:total_count / days_seen / recent_count 或最近出现上下文
  2. 暂不建议加入 stopword
    • 词
    • 理由:为什么当前不建议删掉
  3. 需要人工判断
    • 词
    • 风险点:泛词与有效主题词之间边界不清等

推荐汇报风格:

  • 简短、保守、可审阅
  • 先给判断,再给证据
  • 不输出机器式原始 dump
  • 不默认承诺“已应用”,只汇报“建议”

Phase 2 输入建议

建议给 LLM 的输入包括:

  • data/term_index/term_stats.json 中的高频词与 recent evidence
  • 最近 N 天 data/term_index/daily/*.json 的热点词上下文
  • 当前 configs/term_aliases.json
  • 当前 configs/term_stopwords.json
  • 当前 configs/filter_context.personal.json 中的 interest_keywords
  • 当前 configs/term_watchlist.json

程序层只负责把这些输入整理成紧凑 review context,不负责直接做 alias 决策。

Phase 2 输出建议

建议 LLM 默认输出一份人工审阅汇报,而不是直接写配置:

  • 建议合并
    • from -> to
    • 简短理由
    • 证据(如 total_count / days_seen / recent_count)
  • 暂不建议合并
    • 为什么不建议并掉
  • 需要人工判断
    • 语义相近但风险较高的项

如需结构化输出,可额外补一份 alias_review_candidates.json,但该文件只作为 review 输入,不直接作为自动 apply 指令。

Phase 2 审阅原则

  • 宁可少提,不乱提
  • 优先整理明显同义 / 同概念 / 词形差异
  • 不把公司名、产品名、泛概念词强行混并
  • 默认先汇报,确认后再执行

Phase 2 汇报模板建议

建议 alias review 默认按以下结构汇报给用户:

  1. 建议合并
    • from -> to
    • 理由:为什么判断为同一概念或更合适的标准词
    • 证据:total_count / days_seen / recent_count 或最近出现上下文
  2. 暂不建议合并
    • 候选对
    • 理由:为什么虽然相近,但当前不建议并
  3. 需要人工判断
    • 候选对
    • 风险点:歧义、范围差异、产品名/公司名混淆等

推荐汇报风格:

  • 简短、保守、可审阅
  • 先给判断,再给证据
  • 不输出机器式原始 dump
  • 不默认承诺“已应用”,只汇报“建议”

Phase 2 示例输出

建议合并:

  • Claude code -> Claude Code

    • 理由:明显属于同一产品名,仅是大小写写法不一致。
    • 证据:Claude Code 在最近多日持续出现,而小写写法只是在少量上下文中作为变体出现。
  • Sub-Agent -> SubAgent

    • 理由:更像词形差异,不构成新的独立概念。
    • 证据:两者都围绕同一 agent 架构语境出现,且没有稳定区分语义。

暂不建议合并:

  • Skills ↔ Agent Skills

    • 理由:前者过泛,后者更具体,当前强行归并会损失粒度。
  • Anthropic ↔ Claude

    • 理由:公司名与产品名并不等价,不应直接视为一个关键词。

需要人工判断:

  • AI助手 ↔ AI Agent
    • 风险点:语义可能接近,但中文表述范围更宽,是否并入需要结合你的使用语境判断。